Java 如何安全地强制提交Spring-hibernate事务

Java 如何安全地强制提交Spring-hibernate事务,java,database,spring,hibernate,transactions,Java,Database,Spring,Hibernate,Transactions,我们将spring和hibernate用于web应用程序: 应用程序有一个购物车,用户可以在其中放置物品。为了在不同登录名之间保存要查看的项目,购物车中的项目值存储在表中。提交购物车时,如果我们需要生成订单号,项目将保存到不同的表中 当我们将这些值插入表中以获取订单号时,我们使用来获取最大订单号并向其中添加+1。我们正在使用spring事务管理器和hibernate,在代码流中,我们获取订单号并更新hibernate对象以保存订单号值。调试时,我注意到只有在发出完整事务时,才会插入订单号实体be

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

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

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

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

它只是在spring事务结束时更新内存并将数据插入db。我尝试显式地发出commit to事务

session.getTransaction().commit()

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

非常感谢您的帮助

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

您的第一个问题是,当多个线程执行相同的逻辑时,在编号生成过程中存在串行访问问题。如果您可以使用Oracle序列,这将在数据库级别作为序列自动处理 保证在调用任何次数时返回唯一值。然而,由于现在需要在服务器端管理,所以您需要 在事务边界上围绕数字生成逻辑使用同步机制(选择max和increment by one)。你可以提供服务 方法同步(您的服务类将是singleton和Spring管理的)并声明其周围的事务边界。但是,请注意,这可能会影响性能,并且通常不利于 可伸缩性

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

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


关于flush行为的问题,SQL在flush调用时被发送到数据库,但是在以声明方式提交事务或调用手动提交之前,不会提交数据。但是,根据事务的隔离性质,事务可以看到它要更改的数据,但不能看到其他事务。

我将使用触发器设置订单号,该触发器将在与购物车insert one相同的事务中运行

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

session.refresh(cart);
计数不应由Hibernate管理(
insertable/updateable=false
@Transient
)。

遵循以下步骤:-, 1) 在不同的服务类中创建具有传播的服务方法。 2) 在这个新方法中移动您的代码(您想要刷新到db中的任何代码)。
3) 从现有api调用此方法(由于spring中的代理,我们必须从不同的类调用此新服务方法,否则需要\u new将无法工作,从而确保刷新数据)。

您使用的是哪个数据库?它不支持序列吗?您的所有问题都会得到解决。您的事务的传播类型是什么?@MartinFrey使用oracle数据库时,问题是根据业务规则,订单号应以100000开头,以999999结尾。。我同意如果它是一个序列号,那就不会有问题。@RafikBeldi没有为该方法设置特定的传播参数,我们使用的是下面声明的应用程序上下文级别事务管理@RafikBeldi我使用的是默认的传播\u所需类型。我使用的是oracle悲观锁方法,因为现有代码中的设计更改较少。谢谢,这很有帮助。