我有一个表,有几列和一个序列,为这些列的值增加。对于(简化的)例子:休眠并发问题与选择max(),然后插入max()+ 1
A | B | SEQ
===========
x | x | 1
x | x | 2
x | x | 3
x | y | 1
x | x | 4
z | x | 1
x | y | 2
我有将使用与Hibernate Spring应用和将接受A和B两者,选择A,B的最大值,然后再插入max + 1
多个进程。
所以,上面的例子,如果有人提供A = z和B = X,我们会选择,即可获得1并插入Z,X,2
如果有人提供A = z和B = z(不存在行匹配),过程将查询并找到没有最大值(或最大值为零),然后插入z,z,1.
假设一个简单的序列在这里不起作用,序列不会足够大以允许在A和B的所有值上的一个序列,并且因为实际问题比上面提供的例子更复杂。
我可以想到这个问题的四个解决方案可能工作但我想知道是否有一个更标准的方法来做到这一点,我不知道这些方法可以用Hibernate和没有实现使用自定义Oracle功能:
- 执行
select max()
,尝试插入。如果存在并发问题,则其中一个线程将失败,代码将根据需要重试多次,直到插入工作。有了Hibernate,这可能意味着我们不得不在交易中间手动刷新。 - 执行
select for update
或其他一些机制来锁定我们关心的行(与A和B匹配的行),当我们执行初始的select max()
时。这将阻止其他正在尝试查找max的进程,然后我们可以插入我们的行,并且当txn提交时,正在等待的选择将被允许选择。但我不确定如果表中当前没有与A和B匹配的行,这将如何工作。 - 创建一个存储过程,它自动执行max select和insert操作。尽管如此,我想避免存储过程。
- 在Hibernate中,有没有办法做一个插入(
select max() + 1
)并返回插入到一个语句中的列的值?
感谢您的建议。我们可能不会在此表中删除任何内容。 'partition by'需要原生SQL,我想避免这种情况。 –
你太挑剔了,首先不是storeproc,现在不用原生sql。 Oracle有'row_number()结束(分区' –
你检查过这个吗?http://stackoverflow.com/questions/3616321/concurrent-updates-handling-in-hibernate?rq=1 –