保存后刷新并获取实体(JPA/Spring Data/Hibernate)

新手上路,请多包涵

我有这两个简单的实体 SomethingProperty 。 The Something entity has a many-to-one relationship to Property , so when I create a new Something row, I assign an existing Property

某物:

 @Entity
@Table(name = "something")
public class Something implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "owner")
    private String owner;

    @ManyToOne
    private Property property;

    // getters and setters

    @Override
    public String toString() {
        return "Something{" +
            "id=" + getId() +
            ", name='" + getName() + "'" +
            ", owner='" + getOwner() + "'" +
            ", property=" + getProperty() +
            "}";
    }

财产:

 @Entity
@Table(name = "property")
public class Property implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "shape")
    private String shape;

    @Column(name = "color")
    private String color;

    @Column(name = "dimension")
    private Integer dimension;

    // getters and setters

    @Override
    public String toString() {
        return "Property{" +
            "id=" + getId() +
            ", shape='" + getShape() + "'" +
            ", color='" + getColor() + "'" +
            ", dimension='" + getDimension() + "'" +
            "}";
    }
}

这是 SomethingRepository (春季):

 @SuppressWarnings("unused")
@Repository
public interface SomethingRepository extends JpaRepository<Something,Long> {

}

通过 REST 控制器和 JSON,我想创建一个新的 Something

 @RestController
@RequestMapping("/api")
public class SomethingResource {

    private final SomethingRepository somethingRepository;

    public SomethingResource(SomethingRepository somethingRepository) {
        this.somethingRepository = somethingRepository;
    }

    @PostMapping("/somethings")
    public Something createSomething(@RequestBody Something something) throws URISyntaxException {
        Something result = somethingRepository.save(something);
        return result;
    }
}

这是输入中的 JSON( property id 1 是数据库中的现有行):

 {
  "name": "MyName",
  "owner": "MySelf",
  "property": {
    "id": 1
  }

}

问题是:在方法 .save(something) 之后,变量 result 包含持久实体,但没有字段字段 property null ):

输出JSON:

 {
  "id": 1,
  "name": "MyName",
  "owner": "MySelf",
  "property": {
    "id": 1,
    "shape": null,
    "color": null,
    "dimension": null
  }
}

我希望它们在保存操作后得到验证/返回。

要解决此问题,我必须在 REST 控制器中注入/声明 EntityManager ,并调用方法 EntityManager.refresh(something) (或者我必须调用 .findOne(something.getId()) 方法 2d8f4-e4cf38具有完整的持久化实体):

 @RestController
@RequestMapping("/api")
@Transactional
public class SomethingResource {

    private final SomethingRepository somethingRepository;

    private final EntityManager em;

    public SomethingResource(SomethingRepository somethingRepository, EntityManager em) {
        this.somethingRepository = somethingRepository;
        this.em = em;
    }

    @PostMapping("/somethings")
    public Something createSomething(@RequestBody Something something) throws URISyntaxException {
        Something result = somethingRepository.save(something);
        em.refresh(result);
        return result;
    }
}

通过这种解决方法,我得到了预期的保存结果(使用正确的 JSON):

 {
  "id": 4,
  "name": "MyName",
  "owner": "MySelf",
  "property": {
    "id": 1,
    "shape": "Rectangle",
    "color": "Red",
    "dimension": 50
  }
}

是否有使用 JPA 或 Spring 或 Hibernate 的自动方法/注释,以便拥有“完整”的持久化实体?

我想避免在每个 REST 或服务类中声明 EntityManager ,或者我想避免每次我想要新的刷新的持久实体时调用 .findOne(Long) 方法。

原文由 Andrea Bevilacqua 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 543
1 个回答

无需在每个 资源 中定义 EntityManager ,您可以通过创建 自定义 JpaRepository 来定义一次。 参考

然后直接在每个存储库中使用 refreshEntityManager

参考下面的例子:

自定义存储库接口

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.NoRepositoryBean;

import java.io.Serializable;

@NoRepositoryBean
public interface CustomRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
  void refresh(T t);
}

自定义存储库实现

import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import java.io.Serializable;

public class CustomRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
    implements CustomRepository<T, ID> {

  private final EntityManager entityManager;

  public CustomRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {
    super(entityInformation, entityManager);
    this.entityManager = entityManager;
  }

  @Override
  @Transactional
  public void refresh(T t) {
    entityManager.refresh(t);
  }
}

在 Spring Boot 应用程序类中启用自定义 JPARepository

 @SpringBootApplication
@EnableJpaRepositories (repositoryBaseClass = CustomRepositoryImpl.class)
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

你的东西存储库

public interface SomethingRepository extends CustomRepository<Something, Long> {

}

在 SomethingResource 中直接使用 Refresh (假设 Something 是一个 Entity)

 @RestController
@RequestMapping("/api")
@Transactional
public class SomethingResource {

    private final SomethingRepository somethingRepository;

    public SomethingResource(SomethingRepository somethingRepository) {
        this.somethingRepository = somethingRepository;
    }

    @PostMapping("/somethings")
    public Something createSomething(@RequestBody Something something) throws URISyntaxException {
        Something result = somethingRepository.save(something);
        somethingRepository.refresh(result);
        return result;
    }
}

原文由 Sahil Chhabra 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题