我正在使用Callable接口在serviceImpl中编写多线程程序。我正在使用spring事务管理器。当在DB中执行更新操作时,它会成功执行。但更新的数据不会反映在DB中。但是当我在没有多线程的情况下运行程序,它在DB 中更新。
这是我的配置
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" />
<tx:method name="find*" propagation="NOT_SUPPORTED" />
<tx:method name="get*" propagation="NOT_SUPPORTED" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceOperation" expression="execution(* *..*ServiceImpl.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
我可以转向另一种方法来处理事务管理器。我想知道这种方法是否支持多线程。 所以我的问题是 Spring事务管理器是否支持多线程(我的意思是仅通过声明注释或XML) 为什么更新数据在我的案例中没有反映在数据库中? 什么是最佳替代方法?
答案 0 :(得分:19)
Spring使用的事务上下文存储在线程局部变量中。因此,如果您使用可调用函数启动新线程或在另一个线程中执行代码,则此代码将不会成为Spring事务方面启动的事务的一部分。这就是为什么您的数据不会出现在数据库中的原因。
答案 1 :(得分:3)
你还没有展示你是如何进行多线程的,所以我只能猜到你做了什么:
在YourService.doSomething()中,它是createThreads。对于每个线程,它正在执行与DB相关的操作。是吗?
如另一个答案所述,事务上下文以线程本地方式存储。因此,您在线程中的逻辑与任何事务都没有关联。您可以验证这一点的一点是,除了线程中的逻辑之外,在doSomething()中您还可以执行一些数据库操作。您会发现在doSomething()中执行的db操作是在线程中的操作丢失时提交的。
合理的解决方法之一是,通常我们有一层应用服务作为工作单元,因此,我们有交易边界(类似于您的服务)。您的线程应该调用服务提供的操作。当然,他们将处于不同的交易中。
如果你想在一个事务中全部使用它们,另一种方法是,线程现在执行繁重的工作并将结果发送回原始线程(例如,通过生产者 - 消费者队列,而不是让单个线程执行数据库操作) )。发起的线程负责收集结果并执行数据库操作。
就个人而言,我会尽量避免在不同的线程周围手动传递事务上下文。这简直破坏了陈述性交易的整个想法。
答案 2 :(得分:0)
您可能希望在Spring中实现自己的TransactionSynchronizationManager并将其注入。使用类似InmheritableThreadLocal而不是ThreadLocal。