1

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

    SELECT MAX(serialNumber) + 1 FROM Voucher

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

尽管如此,数据库有时(如果很少)以带有重复序列号的凭证结束。

我的问题是:考虑到我对同步和事务处理相当有信心,是否有什么或多或少明显的我应该知道我错过的休眠,或者我应该回到另一个调试会话,试图找到任何东西否则会导致问题吗?

运行保存进程的服务是一个运行在tomcat6上的web应用,由Spring的HttpRequestHandlerServlet. db 连接由 C3P0 汇集,运行非常基于默认的配置。

我会很感激任何建议

谢谢

4

2 回答 2

0

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

于 2013-09-13T10:04:17.230 回答
0

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

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

于 2013-09-13T12:08:51.027 回答