确保Hibernate会话中的唯一序列号

时间:2013-09-13 09:52:04

标签: java spring hibernate c3p0

我正在编写一个系统,其中包含一个名为Voucher的hibernate管理实体,该实体有一个名为serialNumber的字段,该字段为唯一存在的有效保留唯一编号凭证实例的副本。数据库表中可能还有旧的无效副本,这意味着数据库字段可能不会被声明为唯一。 保存新的有效凭证实例(需要新的序列号)的操作首先在适当的实体上同步。此后整个过程被封装在一个事务中,新值由JPQL

获取
    SELECT MAX(serialNumber) + 1 FROM Voucher

该字段从查询中获取结果,此后保存实例,刷新会话,提交事务,代码最终离开同步块。

尽管如此,数据库有时(如果很少)最终会得到带有重复序列号的凭证。

我的问题是:考虑到我对同步和事务处理非常有信心,我是否应该知道我已经错过的hibernate,或者我应该回到另一个调试会话,尝试找到导致问题的其他原因?

运行保存过程的服务是在tomcat6上运行的Web应用程序,由Spring的HttpRequestHandlerServlet管理。数据库连接由C3P0池化,运行非常基于默认的配置。

我很感激任何建议

由于

2 个答案:

答案 0 :(得分:0)

您可以使用MultipleHiLoPerTableGenerator:它会在当前事务之外生成@Id

答案 1 :(得分:0)

您无需调试即可查找原因。在多线程环境中,它很可能会发生。您正在从表中选择最大值。因此,假设TX1读取最大值a并插入序列号为a+1的行;在此阶段,如果任何TX2读取DB,则最大值仍为a,因为TX1尚未提交其数据。因此,TX2也可以插入序列号为a+1的行。

要避免此问题,您可能决定更改数据库的隔离级别或更改获取序列号的方式(这完全取决于项目的环境)。但一般来说,我不建议更改隔离级别,因为这样的问题需要付出太多努力。