【问题标题】:Hibernate JPA multiple web services updating same tableHibernate JPA 多个 Web 服务更新同一个表
【发布时间】:2017-06-15 02:43:37
【问题描述】:

下面是我们源代码的sn-p...

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

【问题讨论】:

  • 我假设您没有跨应用程序使用 JTA 来同步事务?换句话说,它们是两个独立的应用程序,只是碰巧在处理同一个数据库行的同时处理自己的事务。
  • 我想一个更好的问题是,即使原始 Web 服务成功,您是否关心其他 Web 服务是否失败?
  • 我没有使用它。那是我需要做的吗?我如何实现它?

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


【解决方案1】:

将用户的第一次更新放入标有 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

}

在调用 web 服务之前,内部事务将被提交并且结果对 web 服务可见。请记住,如果 web 服务失败.. 用户的第一次更新不会回滚。

【讨论】:

  • 所以你是说这种情况下只能手动回滚? @Transactional 不能自动处理?
  • 此解决方案也不起作用。用户遇到的问题是需要在 原始 doSomething() 方法将合并发送到数据库之后调用其他 Web 服务。
  • @Naros:真的有解决方案吗?或者当两个 Web 服务更新同一个表时我们的这种逻辑不是一个好习惯?
  • 有几种解决方案,但我需要知道这两个Web服务是在不同的spring应用程序中还是在同一个spring应用程序中?
  • 它们是分开的。它们是部署在同一个应用服务器中的两种不同的 Web 服务
【解决方案2】:

这里最大的问题是您是否需要两个更新都以原子方式发生。在许多应用程序中,这是必需的。在其他情况下,使用最终一致性是可以接受的,这取决于您的要求。

如果您需要原子事务,这意味着两个更新都会发生或都不会发生,您将需要在两个应用程序中利用基于 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 服务的调用需要具有容错性,因此确保最终的一致性合同。

【讨论】:

  • 如果调用第二个Web服务发生异常,如何回滚?
  • 您需要设置 JTA 并让两个应用程序订阅相同的分布式事务来执行此操作。 spring 文档介绍了如何设置 JTA 分布式事务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-07
  • 1970-01-01
  • 2011-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-16
相关资源
最近更新 更多