【发布时间】:2016-12-25 12:32:37
【问题描述】:
我有一个包含几列的表和一个为这些列的值递增的序列。对于(简化)示例:
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 max()时,执行select for update或其他机制来锁定我们关心的行(匹配A 和B 的行)。这将阻止也试图找到最大值的其他进程,然后我们可以插入我们的行,当 txn 提交时,等待的选择将被允许选择。不过,如果表中当前没有匹配 A 和 B 的行,我不确定这将如何工作。 - 创建一个以原子方式执行最大选择和插入的存储过程。不过,如果可能的话,我想避免使用存储过程。
- 在 Hibernate 中,有没有办法进行插入 (
select max() + 1) 并从插入到一个语句中的列中返回值?
【问题讨论】:
标签: java spring oracle hibernate concurrency