Spring Boot - 来自非事务性更新

时间:2018-01-11 21:28:47

标签: java hibernate spring-boot transactions entity

我想知道我最近遇到的一个案子。假设我们有一个服务方法如下:

@Override
public User addUser(UUID organizationId, User user) {
    Organization organization = organizationRepository.findById(organizationId).orElseThrow(IllegalArgumentException::new);
    user.setOrganization(organization);
    organization.getUsers().add(user);
    invitationService.deleteByUserEmail(user.getEmail());
    return user;
}

组织由存储库方法提供:

@Repository
public interface OrganizationRepository extends JpaRepository<Organization, UUID> {

    Optional<Organization> findById(UUID id);
}

添加用户只会因为invitationService.deleteByUserEmail(user.getEmail());存在而起作用。整个方法属于另一个服务,如下所示:

@Override
@Transactional
public void deleteByUserEmail(String userEmail) {
    invitationRepository.deleteByUserEmail(userEmail);
}

我不确定我是否正确理解添加用户的原因。根据Hibernate Docs,仅当实体处于托管状态且更新发生在单个事务中时,才会发生自动更新。如果我的推理是正确的,则会发生以下步骤:

  1. 当请求到达并命中控制器时,实体管理器(休眠会话)将附加到当前线程。 (?)
  2. 处理请求的控制器方法,调用 organizationService.addUser 方法
  3. 组织 findById 方法获取,该方法默认为transactional和readonly(根据 SimpleJpaRepository 实现)。此事务在此之后关闭,但绑定到它的实体管理器仍在运行,组织实体仍然受管理。
  4. 更新发生
  5. 调用invitationService.deleteByUserEmail(user.getEmail()); 。因为它是事务方法,所以启动事务。发生删除,并提交事务并将所有更改刷新到数据库中,甚至是在组织实体中进行的更改。
  6. 尽管 addUser 方法非交易,是否有可能?

1 个答案:

答案 0 :(得分:0)

在您的其中一个配置类中,您可能会注册特殊过滤器,这些过滤器基本上保持会话/实体管理器在整个请求的生命周期内打开:

org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter

org.springframework.orm.hibernate5.support.OpenSessionInViewFilter