Hibernate JPA多个Web服务更新同一个表

时间:2017-01-30 00:23:13

标签: hibernate jpa jpa-2.0 hibernate-mapping spring-transactions

以下是我们源代码的片段......

@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服务完成的更新在记录上完成。

2 个答案:

答案 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服务的调用需要具有容错能力,以确保最终的一致性合同。