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

Spring Boot-从非事务性原因更新中调整事务性方法

龚招
2023-03-14

我在想最近遇到的一个案子。假设我们有一个服务方法,如下所示:

@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文档,只有当实体处于托管状态并且更新发生在单个事务中时,才会发生自动更新。如果我的推理是正确的,就会发生以下步骤:

  1. 当请求到来并命中控制器时,实体管理器(Hibernate会话)被附加到当前线程。(?)
  2. 处理请求的控制器方法调用OrganizationService.AddUser方法
  3. 组织由findById方法获取,该方法在默认情况下是事务性的和只读的(根据SimpleJpaRepository实现)。此事务在此之后关闭,但绑定到该事务的实体管理器仍在运行,并且组织实体仍处于管理状态。
  4. 发生更新
  5. InvitationService.DeleteByUserEmail(user.getEmail());叫做。因为它是事务性方法,所以会启动事务。发生删除,提交事务并将所有更改刷新到数据库中,甚至包括在组织实体中所做的更改。

共有1个答案

公良琛
2023-03-14

在其中一个配置类上,您可能注册了特殊的筛选器,这些筛选器基本上在整个请求的生命周期内保持会话/entitymanager打开:

org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter

org.springframework.orm.hibernate5.support.OpenSessionInViewFilter
 类似资料:
  • 我正在查看一些现有的代码,并想知道在下面的场景中使用Spring的@Transactional注释会发生什么?考虑以下示例: 下面的updateDataBaseItem()方法是常见的,可以从其他非事务性方法和上面的方法调用:

  • 问题内容: 我有一个用@Transactional注释的方法。我从Oracle数据库检索一个对象,更改一个字段,然后从该方法返回。我忘了保存对象,但是发现无论如何都会更新数据库。 applicationContext 我的方法 我的问题是为什么MyObject会持久保存到数据库? 问题答案: 因为hibernate将自动检测对持久实体所做的更改并相应地更新数据库。hibernate参考手册的第11

  • 在MongoDB中,写操作的原子性是在document级别上的,即使修改的是文档中的内嵌部分,写锁的级别也是document上。 当一个写操作要修改多个文档,每个文档的修改是原子性的。整个的写操作并不是原子性的,它可能和其他写操作产生交织。然而你可以使用$isolated隔离操作符来限制写操作,让它不与其他写操作交织。 不隔离性能更高,但是会产生数据的不确定性,隔离写操作,事务性更好。MongoD

  • 我在应用程序中工作。流程和往常一样:。 我用注释了服务层类,从而将该类中的每个方法都标记为事务性的。在服务类中,我调用以获取某个域对象,然后将其转换为对象,该对象将传递给Controller。为了将域对象转换为,我编写了另一个自定义静态类(只有静态方法的类),如,它将进行此转换。 现在,域对象有一些子对象(),它被懒洋洋地加载。因此,当我在中访问子getter方法时,会发出一个额外的数据库调用,该

  • Infinispan作为hibernate二级缓存的更新方式与数据库事务的工作方式不同。我的意思是,在完全提交之前,数据库事务对其他事务不可见。根据日志记录,我观察到事务(JEE MDB)能够部分更新给定的Infinispan更新。具体来说,我的设置如下: Jboss 我似乎看到的是,如果在事务的DB提交之后启动JEE bean,并且我认为是infinispan更新(提交),那么它可以看到一些in

  • 我创建了一个包含@Transactional注释的方面。正在按预期调用我的建议,但新实体AuditRecord从未保存到数据库中,看起来我的@Transactional注释不起作用。 bean上下文如下: 我的切入点是只拦截接口(服务接口)。服务方法可能是也可能不是事务性的。如果服务方法是事务性的,如果建议因某种原因失败,我希望该事务被回滚。 我的问题是:为什么要忽略事务注释?这是我第一次用Spr