以下是我们源代码的片段......
@transactional
public void doSomething(){
User user = (set up user fields)
userDao.merge(user); //update USER table
//call another web service which also updates USER table
//do other processes
}
问题是,来自其他Web服务的更新被userDao.merge的更新覆盖,因为它不会提交合并事务,直到事务方法完成。
你如何处理这种情况?我想要从userdao.merge更新和由其他Web服务完成的更新在记录上完成。
答案 0 :(得分:0)
将用户的第一次更新放在标有REQUIRES_NEW传播的新事务方法中:
@Transactional
public void doSomething(){
updateUser();
//call another web service which also updates USER table
//do other processes
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void udateUser(){
User user = (set up user fields)
userDao.merge(user); //update USER table
}
在调用webservice之前,内部事务将被提交并且结果对webservice可见。请记住,如果Web服务失败,则不会回滚用户的第一次更新。
答案 1 :(得分:0)
这里最大的问题是你是否要求两个更新都以原子方式发生。在很多应用程序中,这是必需的。在其他情况下,使用最终一致性是可以接受的,这取决于您的要求。
如果您需要原子事务,意味着两个更新都发生,或者两者都没有,那么您需要在两个应用程序中利用基于JTA的分布式事务。应用程序服务器提供了开箱即用的功能,您只需配置应用程序即可使用它。
非原子解决方案将使用spring的TransactionSynchronization
接口调用以提供#afterCommit()
回调:
@Transactional
public void doSomething() {
// do stuff
userDao.merge( user );
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronization() {
void afterCommit() {
// call to second service somehow
}
}
);
}
您如何称呼第二项服务完全取决于您。您可以将带有触发器的JMS消息发送到第二个Web服务侦听的队列,也可以直接调用该第二个Web服务。
这里的关键部分是对代理或第二个Web服务的调用需要具有容错能力,以确保最终的一致性合同。