2013-05-30 75 views
3

我使用的可贖回interface.I在serviceImpl編寫多線程程序正在使用Spring的事務manager.When更新操作在DB執行。但更新後的數據不反映DB在成功執行。 但是,當我運行沒有多線程的程序時,它在DB中更新。Spring的事務管理器和多線程

這是我的配置

<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> 

我可以切換到另一種方法爲交易manager.Just我想確認是否屬於這種方法支持或不適合多線程。 所以我的問題是 待辦事項Spring的事務管理器支持多線程(我的意思只是通過聲明註解或XML)爲什麼更新的數據在我的情況並沒有反映在DB ? 什麼是最好的替代方法?

回答

17

Spring中使用的事務上下文被存儲在線程局部變量。因此,如果您啓動一個新線程或使用可調用的代碼在另一個線程中執行代碼,則此代碼不會成爲Spring事務性方面啓動的事務的一部分。這就是爲什麼你的數據不會出現在數據庫中。

+0

是否有可能活動事務傳遞給第二個線程? –

+0

我對此表示懷疑。交易方面如何知道第二個線程是否已完成交易?如果方法在派生線程(或可調用)完成其工作之前返回,誰最終提交事務? –

+0

如果我會這樣做,我負責線程的正確同步。例如,在線程A中開始工作並在線程B中完成它(因此在線程之間傳遞事務)可能很有用。 –

3

你還沒有的節目,你是怎麼做的多線程,所以我只能猜測你做了什麼:

在YourService.doSomething(),它createThreads。對於每個線程,它都在執行與數據庫相關的操作。是對的嗎?

作爲另一個答案desecribed,事務上下文存儲在本地線程的方式。因此,您的線程邏輯與任何事務無關。有一件事你可以驗證這一點,除了線程中的邏輯,在doSomething()中,你也可以做一些數據庫操作。你會發現你在doSomething()中執行的數據庫操作被提交,而線程中的操作丟失。

其中一個合理的解決方法是,通常我們有一層應用服務作爲一個工作單元,因此我們有它的交易邊界(類似於你的服務)。你的線程應該調用服務提供的操作。當然,他們將會在不同的交易中。

如果你想讓它們在一個事務中完成,另一種方法是,線程不用讓單個線程執行數據庫操作,而是讓線程完成繁重的工作,並將結果發回原始線程(由生產者 - 消費者隊列例)。原始線程負責收集結果並執行數據庫操作。

個人而言,我會盡量避免手動傳遞事務上下文各地不同的線程。這只是破壞了聲明式交易的整個想法。

0

您可能想在Spring中實現自己的TransactionSynchronizationManager並注入它。使用InmheritableThreadLocal而不是ThreadLocal。