如何以编程方式在线程中获取事务管理器?
Posted
技术标签:
【中文标题】如何以编程方式在线程中获取事务管理器?【英文标题】:How to programmatically get transaction manager in a thread? 【发布时间】:2011-03-10 11:52:02 【问题描述】:我有一个检票口页面,其中包含两个 Spring 管理的 bean,一个是 DAO,另一个是 Service Object:
public class MergeAccountsPage extends WebPage
@SpringBean
private MergeEmailDao mergeEmailDao;
@SpringBean
private MergingService mergingService;
MergingService
的实现方法大多用 @Transactional
注释,因此涉及 MergingService 的每个操作都可以正常工作。
但问题来了:
Link<Void> link = new Link<Void>("cancelLink")
@Override
public void onClick()
ma.setNewEmail(null);
ma.setNewEmailClicked(null);
ma.setNewEmailSentTime(null);
mergeAccoungDao.update(ma); //not written to DB
setResponsePage(...);
;
该链接将调用mergeAccoungDao.update(ma)
来更新数据库中的一行。
但是数据没有更新到 DB ,我认为是因为 DAO 没有被包裹在 @Transaction 或者 tx:advice
和 aop
标签中。
我想知道有没有办法以编程方式获取事务管理器,并手动打开/关闭事务?
注意:我可以通过在spring的XML中添加这段代码来解决这个问题:
<tx:advice id="txAdviceApp" transaction-manager="transactionManagerApp">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="methods" expression="execution(* destiny.utils.AbstractDao+.*(..))"/>
<aop:advisor advice-ref="txAdviceApp" pointcut-ref="methods"/>
</aop:config>
这样 DAO 的保存/更新/删除将像一个魅力一样工作。
但我不想添加这个配置。因为实际上DAO扩展了一个AbstractDao,还有其他DB/DAO扩展了这个AbstractDao:
public interface AbstractDao<T>
public T get(Serializable id);
public T save(T t);
public T update(T t);
public void delete(T t);
public abstract class AbstractDaoJpaImpl<T> implements AbstractDao<T>
public interface MergeAccountDao extends AbstractDao<MergeAccount>
@Repository
public class MergeAccountDaoImpl extends AbstractDaoJpaImpl<MergeAccount> implements MergeAccountDao
因此,如果这个 AbstractDAO 的 CRUD 被这个 transactionManagerApp “建议”,其他 DAO 可能有问题,因为其他 DAO 可能依赖于 txManagerForum 、 txManagerBank 、 txManagerUser ...等。
回到问题,有没有办法以编程方式获取 txManager ?如:
TransactionManager txManager = TxManagerThreadLocal.get();
txManager.begin();
ma.setNewEmailSentTime(null);
mergeAccoungDao.update(ma);
txManager.commit();
或者有没有更好的方法将交易打包到 DAO 中?
非常感谢。
【问题讨论】:
【参考方案1】:您必须在要使用的类中注入事务管理器。您可以使用构造函数或基于属性的注入或使用自动装配。 获得事务管理器后,您可以使用 Spring 中的编程事务支持来启动和提交事务。这是 Spring 参考 2.5 中的示例代码:
public class SimpleService implements Service
// single TransactionTemplate shared amongst all methods in this instance
private final TransactionTemplate transactionTemplate;
// use constructor-injection to supply the PlatformTransactionManager
public SimpleService(PlatformTransactionManager transactionManager)
Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null.");
this.transactionTemplate = new TransactionTemplate(transactionManager);
public Object someServiceMethod()
return transactionTemplate.execute(new TransactionCallback()
// the code in this method executes in a transactional context
public Object doInTransaction(TransactionStatus status)
updateOperation1();
return resultOfUpdateOperation2();
);
有关详细信息,请参阅reference。
【讨论】:
以上是关于如何以编程方式在线程中获取事务管理器?的主要内容,如果未能解决你的问题,请参考以下文章
如何以与在 Windows 资源管理器中“发送给邮件收件人”相同的方式以编程方式发送电子邮件?
是否可以在资源管理器窗口中以编程方式将文件夹添加到 Windows 10 快速访问面板?
在recyclerview android中以编程方式更改布局管理器
如何以编程方式获取 TaskManager 进程 CPU 使用率(不是 PerfMon API)