简体   繁体   English

Spring 引导 JPA CrudRepository - 实体未附加到持久性上下文

[英]Spring Boot JPA CrudRepository - entities are not attached to persistencecontext

I'm currently implementing my first spring boot application after years of JEE.经过多年的 JEE,我目前正在实施我的第一个 spring 引导应用程序。

I am wondering about JPA / Hibernate behaviour.我想知道 JPA / Hibernate 的行为。 In JEE, once persisted or "find" an @Entity, all changes to this Entity are populated automatically by the JPA implementation to the database without any need to call persist(), flush() etc.在 JEE 中,一旦持久化或“找到”@Entity,对该实体的所有更改都会由 JPA 实现自动填充到数据库,无需调用 persist()、flush() 等。

Now with a CrudRepository changes are only stored to the database if I explicitely call save().现在有了 CrudRepository,只有当我明确调用 save() 时,更改才会存储到数据库中。

My CrudRepository:我的 Crud 存储库:

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

Example code:示例代码:

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

In a JEE implementation right after.setLastName the change would be persisted to the database by Hibernate.在 JEE 实现中,紧随.setLastName 之后,更改将由 Hibernate 持久化到数据库中。 In my spring-boot service it istn't.在我的 spring-boot 服务中它不是。 It's usually explicitely necessary to issue.save() any idea why and how I could gain the same behaviour like in JEE?通常明确需要 issue.save() 任何想法为什么以及如何获得与 JEE 中相同的行为?

Actually Spring boot Repository uses JPA behind the scene to persist entity to the database.实际上 Spring boot Repository 在后台使用 JPA 将实体持久化到数据库。 but I want to explain what happen behind the scene.但我想解释一下幕后发生的事情。 You know there is an EntityManager which has a Persistence Context.您知道有一个具有持久性上下文的EntityManager When EntityManager created, it will attach itself to the current TransactionManager so that when that transaction committed all data within that Persistence Context will be committed to the database or on the other hand when transaction RollBack all data within that Persistence Context will be roll backed.EntityManager创建时,它会将自己附加到当前的TransactionManager ,以便当该事务提交该持久性上下文中的所有数据时,该持久性上下文中的所有数据将被提交到数据库,或者另一方面,当该持久性上下文中的事务回滚时,该持久性上下文中的所有数据都将被回滚。 Here in Spring Repository you can see that there is no Persistence Context explicitly.在 Spring 存储库中,您可以看到没有明确的持久性上下文。 This Persistence Context exist but works behind the scene and when findById method return and deliver you the entity, that entity is not attached to persistence Context actually this context is closed when findById return.此持久性上下文存在但在幕后工作,当findById方法返回并将实体交付给您时,该实体未附加到持久性上下文实际上此上下文在 findById 返回时关闭。

But Spring Repository make all this proccess transparent to the user since it uses EntityManager and Transaction Manager behind the scene.但是 Spring Repository 使所有这些过程对用户透明,因为它在后台使用EntityManager和 Transaction Manager。 actually it is the magic wand of Spring that let you omit all these boilerplate code.实际上是 Spring 的魔杖让你省略了所有这些样板代码。 But this magic didn't come without any drawback, in your updateUser method you don't open and you don't commit any transaction but they acctually opened and committed two times behind the scene, once when you call findById method, it open transaction, fetch data and commit it.但是这种魔法并非没有任何缺点,在您的updateUser方法中,您没有打开并且您没有提交任何事务,但它们实际上在后台打开并提交了两次,当您调用findById方法时,它会打开事务,获取数据并提交。 And again when you save data here again transaction open, and Persistence Context content save to database when transaction committed.当您再次在此处保存数据时,事务打开,并且持久性上下文内容在事务提交时保存到数据库。 imagine you have some transactional process in your special method in that case you should think about that specially.假设您在特殊方法中有一些事务处理,在这种情况下您应该特别考虑一下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM