spring-data-jpa 升级后,异步事务性保存在Spring中不起作用

k75qkfdt  于 2022-11-10  发布在  Spring
关注(0)|答案(1)|浏览(263)

我们将Sping Boot 从1.5.8升级到2.6.2。它引入了一个让我们困惑的问题:事务性存储不是从派生线程内部进行处理。
我们在Mysql数据库上使用JPA托管实体,并向下调用CrudRepository来保存它们。
主线程内的事务工作正常。但是,当从异步操作调用时,事情会出错:

  • async和sync调用都通过Springx 1 m0n1x方法,但是在async操作的情况下,entityManager返回一个空id的对象来持久化。
  • 我在这两种类型的调用中都遵循了该流程,可以看到保存向下传播到org.hibernate.internal.SessionImpl服务。
  • 从那里它进入AbstractSaveEventListener.class,这就是差异所在。在performSaveOrReplicate方法(hibernate-core:5.6.3)中,inTrx布尔值在异步工作流中为false,而在同步工作流中为true。因此,shouldDelayIdentityInserts标志被设置,并且似乎没有为该线程中的任何实体生成id。

我们已经尝试了不同的方法来实现这个功能,例如,我们使用transactionTemplate来实现一些特定的控制,但是这并没有改变行为。
我们最初是通过使用ApplicationEventPublisher创建一个事件来创建这个异步进程的。我们也尝试使用completablefuture和其他结构来获得相同的结果,并使用@Async注解该方法并直接调用它。

rkttyhzu

rkttyhzu1#

问题是,升级到 Boot 后,SpringBatch实现了一个新的事务管理器。
我们没有意识到的是,此事务管理器被自动连接到我们的其他服务中,并且在此线程上下文中不工作。您不希望与您的API/杂项服务共享批处理Tx管理器。在此处声明特定的事务管理器以使它们保持分离解决了此问题。
下面是一个使用Primary注解标记PlatformTransactionManager以显式测试其用法的示例。

@Primary
@Bean
public PlatformTransactionManager platformTransactionManager(DataSource dataSource) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory(dataSource).getObject());
    return transactionManager;
}

相关问题