我们将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注解该方法并直接调用它。
1条答案
按热度按时间rkttyhzu1#
问题是,升级到 Boot 后,SpringBatch实现了一个新的事务管理器。
我们没有意识到的是,此事务管理器被自动连接到我们的其他服务中,并且在此线程上下文中不工作。您不希望与您的API/杂项服务共享批处理Tx管理器。在此处声明特定的事务管理器以使它们保持分离解决了此问题。
下面是一个使用
Primary
注解标记PlatformTransactionManager以显式测试其用法的示例。