0

我正在使用序列将域对象实例保存在我的 oracle 数据库中。我对数据库中的每个表都有一个序列。例如,当我在用户或资源上使用保存功能时,它在第一次尝试时创建了一个新资源,但使用的 ID 是 70?该序列显示了正确的下一个数字 - 42,因为表中的最大 id 为 41。为什么 id=70 用于插入新资源?

同样从下一次尝试所有插入都失败并出现此错误

org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch update; SQL [insert into GRARESOURCE (decomm
issioned, disabled, criticality, resourceClass, resourceGroupId, resourceName, ownerId, resourceSegmentId, resourceTypeId, riskSco
re, targetIP, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]; constraint [GRA.SYS_C0012183]; nested exception is org.hibernate.e
xception.ConstraintViolationException: Could not execute JDBC batch update

不知道出了什么问题,因为这是在代码重组之后发生的......我们将代码移动到新包中......

编辑:我找到了原因,请参阅我的回复..谢谢大家

4

4 回答 4

1

序列可能会浪费数字,即表中的每条记录不一定是一个接一个,没有间隙。换句话说,即使之前的 DB 记录的 ID=41,您的数据也跃升至 70,这并不表示存在问题。

于 2012-03-14T01:23:29.260 回答
1

因为表中的最大 id 是 41

序列看不到表的最大值并获得下一个。它们存储当前序列号,您将使用下一个值。

您可以通过以下方式检查实际数字:

select mysequence.currval from dual

您的问题在于GRA.SYS_C0012183约束。看看这个检查什么,如果这是你的主键,也许你可以使用一些更易读的名字,比如 MY_TABLE_PK...

于 2012-03-14T01:28:04.183 回答
0

SYS_C0012183主键约束吗?它是否不仅定义了id列(我假设它是由序列填充的列)?

  • 你如何确定序列的下一个值是 42?您是否为此运行单独的查询?
  • 您是否期望序列为您提供无间隙的数字?如果是这样,那就是您的期望有问题。序列返回不同的值,但它们不保证没有间隙(实际上,您可以保证会有间隙,因为数据库关闭或序列从共享池中清除或事务回滚)。
  • 你如何使用序列?桌子上有触发器吗?还是 Hibernate 配置为使用该序列?如果 Hibernate 配置为使用该序列,请发布该配置。
于 2012-03-14T01:23:24.073 回答
0

我意识到问题的主要原因。我以前使用过 SequencePerTableOracleDialect,这是从 Burt Beckwith 之前的一篇文章中得到的。该方言在应用程序启动时为每个表创建一个新序列,类似于域类转换为表。方言还确保每个表 id 序列仅通过其序列进行管理,并且数据库中的所有插入都不使用公共序列(这是默认策略)在代码重组期间,我删除了自定义方言并使用默认10g方言。

这就是造成问题的原因!

我在关联序列的下一个值字段的表中看到下一个数字,我知道资源表中的下一个 val = 42 是正确的,因为资源表中的 max(id) 是 41。

非常感谢大家的洞察力,这在某种程度上帮助我回忆起真正的原因!对于那些需要了解更多关于自定义方言的人,这里

于 2012-03-14T02:03:24.153 回答