Dav*_*rks 10 java spring transactions spring-mvc
环境:Spring 3,自定义事务管理,JDBC事务
我刚刚阅读了有关使用事务模板处理事务管理的Spring文档.它似乎过于复杂,所以我想问:
我的大部分交易都与JDBC有关,这意味着我只是声明@Transactional
我的服务.但是现在我正在对另一个需要回滚的站点进行REST服务调用,如果以下任何JDBC操作失败,我将在这种情况下提供回滚代码.
正如我在我的方法进步,在我的交易-我想保存到REST服务调用的引用(回滚操作需要),以及异常时我只是希望有一个方法myCustomRollback()
叫可以访问以前存储的对象.
为什么不在transactionTemplate中提供一个映射来存储东西并在@Transactional
注释上定义自定义回滚方法?
这就是我想到的方式,我不会按照Spring的想法.有人可以帮助我弥合我想要的东西和我如何在Spring中最有效地完成它之间的差距吗?我只需要为一些特殊情况操作执行此操作.
对于还在读这篇文章的人:
我解决了弹簧事件的类似问题 - 正如Den Roman在选项3中所建议的那样.这是基本思想(场景是虚构的):
每当我执行需要与事务一起回滚的外部操作时,我@Transactional
使用spring(org.springframework.context.ApplicationEventPublisher
)的支持在我的方法中发布一个事件:
@Transactional
public String placeOrder(Order order) {
String orderId = orderServiceGateway.createOrder(order);
applicationEventPublisher.publishEvent(new OrderCreatedEvent(orderId));
workflowService.startWorkflow(orderId);
return orderId;
}
Run Code Online (Sandbox Code Playgroud)
事件本身可以是任何对象 - 我创建了一个POJO,其中包含有关要删除的远程实体的详细信息.
然后我注册了一个绑定到事务阶段的特殊事件监听器 - 在我的例子中是回滚:
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void rollBackOrder(OrderCreatedEvent orderCreatedEvent) {
String orderId = orderCreatedEvent.getOrderId();
orderServiceGateway.deleteOrder(orderId);
}
Run Code Online (Sandbox Code Playgroud)
当然,建议从回滚操作中捕获并记录异常,而不是从placeOrder()
方法中丢失原始异常.
默认情况下,这些事件是同步的,但可以通过其他配置使它们异步.
这是一篇关于这种机制的非常好的文章,包括详细的配置和陷阱:事务同步和Spring应用程序事件(DZone)
虽然我不喜欢100%的解决方案,因为它使用事件发布的东西混淆了业务逻辑并且绑定到spring,它肯定会做我期望它做的事情,并且可以将事务方法中的上下文传递给回滚方法 - 这不是通过事务方法之外的传统try/catch块提供的(除非你把你的上下文放在异常本身,这不是很好).
我已经重读了几次你的问题,我不确定我完全理解你的问题.我假设您正在执行someCode,如果失败,您想执行myCustomRollback,其中包含someCode的一些信息.所以我会尝试提供一个通用的答案.
如果你想让spring回滚一些代码.它只会回滚rollBackAble,就像jdbc事务一样.假设您有一个执行2次调用的方法.
@Transactional
public void doStuff(SomeEntity entity, File file) {
persist(entity);
customFileService.createOnFileSystem(file);
throw new RunTimeException();
}
Run Code Online (Sandbox Code Playgroud)
所以上面的代码将始终回滚.它将撤消实体的持久性,但不会撤消文件的创建,因为它不是由Spring事务管理的,除非您为它提供自定义实现.
其次,Spring提供了两种处理事务的方法:
aspectJ方法似乎更难配置,但不是那么多,并且更容易使用.因为任何使用@Transactional注释的内容都将嵌入(编织)代码.对于Spring AOP,情况并非如此.例如在Spring中的事务内部方法调用将被忽略!因此aspectJ提供了一种更直观的方法.
回到我认为你的问题是(代码全部在1类):
public void doSomeCode() {
Object restCall = initialize();
try {
execute(restCall);
} catch (CustomException e) {
myCustomRollback(restCall; e);
}
}
@Transactional(rollbackFor = CustomException.class)
private void execute(Object restCall) throws CustomException {
// jdbc calls..
restCall = callRest(restCall);
throw new CustomException();
}
void myCustomRollback(Object restCall, CustomException e) {
...
}
Run Code Online (Sandbox Code Playgroud)
上面的代码只适用于AspectJ!由于你的内部方法调用似乎也是私有的!运行时的AOP无法处理此问题.
那么所发生的事情是执行中的所有内容(即rollbackAble)都将被回滚.在doStuff中,您可以获得有关执行中使用的对象的信息,您现在可以在myCustomRollback中手动回滚REST内容.
不确定我是否正确回答了这个问题,但我希望它可以帮助有类似问题的人.
Ana*_*rma -1
您可以使用 AfterThrowing 建议(当抛出异常时)并myCustmRollback()
在那里调用您的方法(),您可以使用TransactionSynchronizationManager
类来获取当前事务并将其回滚...
或者..您可以使用aroundadvice来开始&提交/回滚您的事务(这样您可以通过使用类来使用spring提供的事务管理器TransactionSynchronizationManager
)
归档时间: |
|
查看次数: |
15731 次 |
最近记录: |