【问题标题】:How to force commit Spring - hibernate transaction safely如何强制提交 Spring - 安全地休眠事务
【发布时间】:2014-06-26 16:43:46
【问题描述】:

我们在 web 应用程序中使用 spring 和 hibernate: 该应用程序有一个购物车,用户可以在其中放置物品。为了保存不同登录之间要查看的项目,购物车中的项目值存储在表中。提交购物车时,商品将被保存到不同的表中,我们需要生成订单号。

当我们将值插入表中以获取订单号时,我们使用获取最大订单号并将其添加 +1。我们正在使用 spring 事务管理器和休眠,在代码流中我们获取订单号并更新休眠对象以保存订单号值。当我调试时,我注意到只有在发出完整的事务时才会插入订单号实体 bean。

这里的问题是当我们同时向服务器提交两个请求时,使用了相同的订单号,并且只插入了一个请求数据。无法插入另一个唯一的请求值。 表中的订单号是唯一的。

我注意到,在调试持久层时,即使在发出会话刷新之后,也没有将其插入数据库 session.flush()

它只是在 spring 事务结束时更新内存并将数据插入到 db 中。我尝试明确发布对事务的提交

session.getTransaction().commit();

这会立即将值插入数据库,但在进一步的代码流中显示无法启动事务的消息。

非常感谢任何帮助。

添加: 我使用的 Oracle 数据库。 该表有一个唯一的序列号,并且订单号也映射到它。

【问题讨论】:

  • 您使用的是哪个数据库?它不支持序列吗?你所有的问题都会得到解决。
  • 你的交易的传播类型是什么?
  • @MartinFrey 使用 oracle 数据库,问题是根据业务规则,订单号应以 100000 开头,并以 999999 结尾。我同意如果它是一个序列号,那不会有问题。
  • @RafikBeldi 该方法没有设置特定的传播参数,我们使用如下声明的应用程序上下文级别事务管理
  • @RafikBeldi 我正在使用默认的 Propagation_required 类型。

标签: java database spring hibernate transactions


【解决方案1】:

按照以下步骤操作:-, 1) 在不同的服务类中创建一个传播 REQUIRES_NEW 的服务方法。 2)在这个新方法中移动你的代码(无论你想刷新到 db 的任何代码)。 3)从现有的api调用这个方法(由于spring的代理,我们必须从不同的类调用这个新的服务方法,否则REQUIRES_NEW将不起作用,这确保您的数据刷新)。

【讨论】:

    【解决方案2】:

    我将使用触发器设置订单号,该触发器将在与购物车插入的同一事务中运行。

    保存购物车后,要查看更新的订单数量,您必须致电:

    session.refresh(cart);
    

    计数不应由 Hibernate 管理(insertable/updatable = false 或 @Transient)。

    【讨论】:

      【解决方案3】:

      您的第一个问题是多个线程执行相同逻辑时围绕数字生成的串行访问。如果您可以使用 Oracle 序列,这将在数据库级别自动处理为序列 保证在调用它们的任何次数都返回唯一值。但是,由于现在需要在服务器端进行管理,因此您需要 在事务边界上围绕数字生成逻辑(选择最大值并递增一)使用同步机制。您可以使服务 方法同步(您的服务类将是单例和 Spring 管理的)并声明它周围的事务边界。但是请注意,这会对性能产生影响,并且通常不利于 可扩展性。

      另一个选项可能是这种情况的变体 - 将要分配的 id 存储在一个单独的表中,其中有一列“currentVal”并使用悲观锁 以获得下一个号码。这样,主表就不会有任何大锁。这样,在主实体创建事务完成时,将为序列生成器代码保持锁定。这些技术背后的主要思想是序列化 访问序列生成器并持有锁直到主实体事务提交。还要尽可能晚地延迟数字生成器。

      如果在您的设计中使用触发器很好,@Vlad 建议的解决方案是一个很好的解决方案。

      关于您关于刷新行为的问题,SQL 在刷新调用时发送到数据库,但是在以声明方式提交事务或调用手动提交之前不会提交数据。但是,事务可以看到它打算更改的数据,但不能看到其他事务,具体取决于事务的隔离性质。

      【讨论】:

      • 我使用了 oracle 悲观锁方法,因为对现有代码的设计更改较少。谢谢,它有帮助。
      猜你喜欢
      • 2018-05-06
      • 1970-01-01
      • 1970-01-01
      • 2011-04-05
      • 2013-05-04
      • 1970-01-01
      • 2017-10-20
      • 2021-12-08
      • 2015-10-15
      相关资源
      最近更新 更多