java Spring 事务管理器和多线程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16835974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring transaction manager and multithreading
提问by abishkar bhattarai
I am writing multithreading program in serviceImpl using Callable interface.I am using spring transaction manager.When update operation is executed in DB ,it is executed successfully .But the updated data is not reflected in DB.But When i run program without multithreading it is updated in DB.
我正在使用 Callable 接口在 serviceImpl 中编写多线程程序。我正在使用 spring 事务管理器。在 DB 中执行更新操作时,它执行成功。但更新的数据未反映在 DB 中。但是当我在没有多线程的情况下运行程序时,它会在 DB 中更新。
This is my configuration
这是我的配置
<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>
I can shift to another approach for transaction manager.Just i want to get confirm if this approach supports or not for multithreading. So my question is Do spring transaction manager supports multithreading(I mean just by declaring annotation Or XML ) Why updated data is not reflected in DB in my case?What can be the best alternative approach ?
我可以转向事务管理器的另一种方法。我想确认这种方法是否支持多线程。所以我的问题是 spring 事务管理器是否支持多线程(我的意思是仅仅通过声明注释或 XML )为什么更新的数据在我的情况下没有反映在 DB 中?什么是最好的替代方法?
回答by JB Nizet
The transactional context used by Spring is stored in a thread-local variable. So if you start a new thread, or execute code in another thread using a callable, this code won't be part of the transaction started by the Spring transactional aspect. That's why your data doesn't appear in the database.
Spring 使用的事务上下文存储在线程局部变量中。因此,如果您启动一个新线程,或使用可调用对象在另一个线程中执行代码,则此代码将不会成为 Spring 事务方面启动的事务的一部分。这就是为什么您的数据不会出现在数据库中的原因。
回答by Adrian Shum
You haven's show how you are doing multi-threading, so I can only guess what you have done:
你还没有展示你是如何进行多线程的,所以我只能猜测你做了什么:
In YourService.doSomething(), it createThreads. For each thread, it is doing DB related actions. Is that right?
在 YourService.doSomething() 中,它创建线程。对于每个线程,它正在执行与数据库相关的操作。是对的吗?
As desecribed in another answer, transaction context is stored in thread local manner. Therefore, your logic in thread has no association with any transaction. One thing you can verify this is, apart from the logics in threads, in doSomething() you also do some DB actions. You will find that db actions you performed in doSomething() is committed while actions in threads are lost.
如另一个答案中所述,事务上下文以线程本地方式存储。因此,您在线程中的逻辑与任何事务都没有关联。您可以验证的一件事是,除了线程中的逻辑之外,在 doSomething() 中您还可以执行一些 DB 操作。您会发现在 doSomething() 中执行的数据库操作已提交,而线程中的操作丢失。
One of the reasonable way to solve is, normally we have a layer of application service which serves as a unit-of-work, and hence, we have transaction boundary on it (similar to your Service). Your thread should invoke the operations provided by the service. Of course, they will be all in different transaction.
一种合理的解决方法是,通常我们有一层应用服务作为工作单元,因此,我们在其上有事务边界(类似于您的服务)。您的线程应该调用服务提供的操作。当然,它们都将处于不同的事务中。
If you want them all in one transaction, another way is, instead of let individual thread do the DB action, threads now do the heavy work and post the result back to the originated thread (by a producer-consumer queue for example). The originated thread is responsible to gather the result and perform DB actions.
如果您希望它们都在一个事务中,另一种方法是,线程现在执行繁重的工作并将结果发布回原始线程(例如通过生产者-消费者队列),而不是让单个线程执行 DB 操作。起源线程负责收集结果并执行数据库操作。
Personally I would try to avoid manually passing the transaction context around different thread. This is simply ruining the whole idea of declarative transaction.
就我个人而言,我会尽量避免在不同线程之间手动传递事务上下文。这只是破坏了声明式交易的整个想法。
回答by Den Roman
You might want to implement your own TransactionSynchronizationManager in Spring and inject it. Use something like InmheritableThreadLocal instead of ThreadLocal.
您可能希望在 Spring 中实现您自己的 TransactionSynchronizationManager 并注入它。使用类似 InmheritableThreadLocal 的东西而不是 ThreadLocal。