Spring Boot JPA CrudRepository - 实体未附加到persistencecontext

Posted

技术标签:

【中文标题】Spring Boot JPA CrudRepository - 实体未附加到persistencecontext【英文标题】:Spring Boot JPA CrudRepository - entities are not attached to persistencecontext 【发布时间】:2020-09-29 01:33:34 【问题描述】:

经过多年的 JEE,我目前正在实现我的第一个 Spring Boot 应用程序。

我想知道 JPA / Hibernate 的行为。在 JEE 中,一旦持久化或“找到”@Entity,对此实体的所有更改都会由 JPA 实现自动填充到数据库中,无需调用 persist()、flush() 等。

现在使用 CrudRepository 的更改只有在我明确调用 save() 时才会存储到数据库中。

我的 CrudRepository:

public interface UserAccountRepository extends CrudRepository<UserAccount, Long> 
    public Optional<UserAccount> findByEmail(String email);
    public Optional<UserAccount> findByVerificationCode(String verificationCode);

示例代码:

public void updateUser(Long userId, String newName) 
    UserAccount userAccount = userAccountRepository.findById(userId)
            .orElseThrow(() -> new NotFoundException("Userid not found"));

    userAccount.setLastName(newName);        
    //Stop here in JEE
    userAccountRepository.save(userAccount);
 

在 .setLastName 之后的 JEE 实现中,更改将由 Hibernate 持久保存到数据库中。在我的 spring-boot 服务中它不是。通常明确需要发出 .save() 任何想法为什么以及如何获得与 JEE 中相同的行为?

【问题讨论】:

【参考方案1】:

实际上 Spring boot Repository 在后台使用 JPA 将实体持久化到数据库中。但我想解释一下幕后发生的事情。你知道有一个EntityManager 有一个持久性上下文。创建EntityManager 时,它将自己附加到当前TransactionManager,以便当该事务提交该持久性上下文中的所有数据时,该持久性上下文中的所有数据将被提交到数据库,或者另一方面,当事务回滚该持久性上下文中的所有数据时,该持久性上下文中的所有数据将被提交回滚。在 Spring Repository 中,您可以看到没有显式的持久性上下文。此持久性上下文存在但在幕后工作,当findById 方法返回并向您提供实体时,该实体未附加到持久性上下文实际上此上下文在 findById 返回时关闭。

但是 Spring Repository 使所有这些过程对用户透明,因为它在幕后使用 EntityManager 和事务管理器。实际上是 Spring 的魔杖让你省略了所有这些样板代码。但是这种魔法并非没有任何缺点,在您的 updateUser 方法中,您没有打开并且您没有提交任何事务,但它们实际上在幕后打开并提交了两次,一次是当您调用 findById 方法时,它打开事务,获取数据并提交它。当您再次在此处保存数据时,事务打开,并且持久性上下文内容在事务提交时保存到数据库。想象一下,您的特殊方法中有一些事务处理,在这种情况下,您应该特别考虑一下。

【讨论】:

以上是关于Spring Boot JPA CrudRepository - 实体未附加到persistencecontext的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot(十五):spring boot+jpa+thymeleaf增删改查示例

[Spring Boot] Adding JPA and Spring Data JPA

spring-data-jpa 和 spring-boot-starter-data-jpa 的区别

spring boot jpa

Spring Boot 整合Spring Data JPA

Spring Boot中使用Spring Data JPA示例