当前位置: 首页 > 知识库问答 >
问题:

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

淳于健
2023-03-14
@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(Spring):

@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;
    }
}
{
  "name": "MyName",
  "owner": "MySelf",
  "property": {
    "id": 1
  }

输出JSON:

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

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

要解决此问题,我必须在REST控制器中注入/声明EntityManager,并调用EntityManager.Refresh(something)方法(或者我必须调用.Findone(something.GetId())方法以获得完整的持久化实体):

@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;
    }
}
{
  "id": 4,
  "name": "MyName",
  "owner": "MySelf",
  "property": {
    "id": 1,
    "shape": "Rectangle",
    "color": "Red",
    "dimension": 50
  }
}

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

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

共有1个答案

丁灿
2023-03-14

不必在每个资源中定义EntityManager,您可以通过创建自定义JPararePository来定义它一次。引用

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

请参考下面的示例:

CustomRepository接口

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);
}

CustomRepository实现

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应用程序类中启用自定义JPararePository

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

您的Something存储库

public interface SomethingRepository extends CustomRepository<Something, Long> {

}

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

@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;
    }
}
 类似资料:
  • 我通过Spring Data Jpa save()方法将我的实体保存到数据库中。此方法返回已保存的实体对象,但是如果Im保存新实体,则返回的对象不填充例如@manytomany完整实体。 如何解决那个问题?

  • 我在Spring Boot中使用Spring Data JPA。 在使用Spring Data Jpa存储库将一个实体保存到数据库后,我不会得到整个实体。即只获取我传递给save()的值。 组织实体: 控制器类: 服务类别:

  • 我有一个关于spring boot和hibernate的项目。从数据库中选择数据时一切正常,但在插入实体后我遇到了一个问题。插入后未提取实体关系。我尝试了JpaRepository保存并刷新,但没有成功。此外,我还尝试了findById,但没有成功。我如何解决这个问题? 我的实体; 我的存储库; 我的服务方式; 我的控制器;使用saveOneCommentendpoint 再次插入并查找后,用户和

  • null 我能找到的使用JPA/Hibernate的唯一有效解决方案是执行以下步骤。这是因为hibernate将实体保留在第一级缓存中,直到事务结束。 创建新实体 强制快速刷新() 分离实体 这样做的开销是 null 使用JDBC或JdbcTemplate,但您必须为实体编写自己的插入 所以问题是:是否存在同时坚持和分离的可能性,或者甚至更好地坚持而不成为被管理的?

  • Thread[hz._hzinstance_1_dev.partition-operation.thread-3,5,_hzinstance_1_dev]无法进行远程调用:com.hazelcast.collection.impl.collection.operations.CollectionAddOperation{serviceName='hz:impl:setService',identi

  • 问题内容: 问题基本上与下面的问题相同: JPA级联仍然存在,对分离实体的引用将引发PersistentObjectException。为什么? 我正在创建一个引用现有的分离实体的新实体。现在,当我将此实体保存在spring数据存储库中时,会引发异常: 如果我们查看Spring数据JPA的源代码中的save()方法,则会看到: 如果我们看一下isNew() 因此,基本上,如果我保存()一个新实体,