如何在Spring编程事务中获取transactionManager引用
我想在从队列接收消息的JMS应用程序中使用spring编程事务。同时,我希望将队列包括在事务范围中 使用Spring DefaultMessageListenerContainer并在其中注入事务管理器。但是,不确定如何获取此事务的引用以编程方式提交或回滚如何在Spring编程事务中获取transactionManager引用,spring,transactions,jms,Spring,Transactions,Jms,我想在从队列接收消息的JMS应用程序中使用spring编程事务。同时,我希望将队列包括在事务范围中 使用Spring DefaultMessageListenerContainer并在其中注入事务管理器。但是,不确定如何获取此事务的引用以编程方式提交或回滚 我在这里阅读并理解“在事务中处理消息” 我的两项要求是— 1) XA事务管理器, 2) 使用编程事务-这里我需要帮助如何在代码中获得对spring启动的事务的引用,以便我能够以编程方式处理事务您首先必须注入org.springframew
我在这里阅读并理解“在事务中处理消息” 我的两项要求是— 1) XA事务管理器,
2) 使用编程事务-这里我需要帮助如何在代码中获得对spring启动的事务的引用,以便我能够以编程方式处理事务您首先必须注入
org.springframework.transaction.PlatformTransactionManager
-它与所有其他bean一样是一个普通bean:
@Resource
private PlatformTransactionManager transactionManager;
现在,您可以将其与交易模板
一起使用:
final TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(new TransactionCallback<String>() {
@Override
public Object doInTransaction(TransactionStatus status) {
transactionManager.rollback(status);
return ":-(";
}
});
如果从@Transactional
方法抛出运行时异常
,它将自动回滚该事务。否则它将被提交
请注意,这并不意味着JMS和数据库在同一事务上工作!当您抛出异常时,JMS代理将尝试重新传递消息,但是在提交DB事务后,代理很可能会失败。如果您需要100%确保JMS和DB更新都是原子的,那么您需要分布式事务管理器
Spring使用PlatformTransactionManager
抽象底层事务管理器在运行时,我们可以注入特定于平台的事务管理器,如下图所示 我们可以通过以下两种方式获得spring编程方法中的事务管理器引用:
平台事务管理器
:我们必须显式创建一个事务定义
和事务状态
对象 @Resource
private PlatformTransactionManager transactionManager;
public void create(String name, Integer age, Integer marks, Integer year){
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
//jmsTemplate statements
transactionManager.commit(status);
} catch (DataAccessException e) {
System.out.println("Error in creating record, rolling back");
transactionManager.rollback(status);
throw e;
}
交易模板
:TransactionDefinition
和TransactionStatus
对象。TransactionTemplate
提供了一个名为execute的回调方法,我们可以在其中添加我们想要包装在事务中的业务逻辑
我们可以使用两种类型的回调方法包装代码,即TransactionCallbackWithoutResult
和TransactionCallback(T)
例如:
@Resource
private TransactionTemplate transactionTemplate;
public void deleteUser(final int uid) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus paramTransactionStatus) {
try{
//statements
}catch (Exception e) {
//use this to rollback exception in case of exception
paramTransactionStatus.setRollbackOnly();
}
}
});
}
public int insertUser(final User user) {
//use TransactionCallback handler if some result is returned
return transactionTemplate.execute(new TransactionCallback<Integer>() {
public Integer doInTransaction(TransactionStatus paramTransactionStatus) {
//statements
}
});
}
@Resource
私有事务模板TransactionTemplate;
公共void deleteUser(最终int-uid){
transactionTemplate.execute(新建TransactionCallbackWithoutResult(){
受保护的void doInTransactionWithoutResult(TransactionStatus paramTransactionStatus){
试一试{
//声明
}捕获(例外e){
//使用此选项可在出现异常时回滚异常
paramTransactionStatus.setRollbackOnly();
}
}
});
}
公共int插入器(最终用户){
//如果返回某些结果,请使用TransactionCallback处理程序
返回transactionTemplate.execute(新建TransactionCallback(){
公共整数doInTransaction(TransactionStatus参数TransactionStatus){
//声明
}
});
}
这是否会将消息放回队列?i、 e.队列是否在事务范围内?我是否可以直接使用transactionManager而不使用TransactionTemplate?@user1166503:这有点复杂(理论上)-在默认配置中,会发生以下情况:JMS tx start、DB tx start、DB tx commit、JMS tx commit。若在第3步和第4步之间发生了什么,JMS tx将回滚,但DB已经提交。这是一个问题,因为数据被持久化,但消息将被放回队列。/是的,您可以直接使用PlatformTransactionManager
,但这有点不方便,模板试图简化它。这有帮助,但仍然不确定您提供的事务回滚代码将如何添加到onMessage()方法中?该方法具有@Transactional注释和编程事务。@user1166503:第一个代码段创建一个新的DB事务并回滚。后者将同时回滚,因为异常会转义onMessage
(准确地说,您还必须添加自定义,因为Spring会吞下JMSonMessage()
异常。我使用第一种方法,注意到一些异常会使连接处于错误状态。因此,以下使用池中该连接的请求会引发错误。除了回滚之外,还有什么其他要做的吗?
@Resource
private TransactionTemplate transactionTemplate;
public void deleteUser(final int uid) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus paramTransactionStatus) {
try{
//statements
}catch (Exception e) {
//use this to rollback exception in case of exception
paramTransactionStatus.setRollbackOnly();
}
}
});
}
public int insertUser(final User user) {
//use TransactionCallback handler if some result is returned
return transactionTemplate.execute(new TransactionCallback<Integer>() {
public Integer doInTransaction(TransactionStatus paramTransactionStatus) {
//statements
}
});
}