【发布时间】:2014-09-22 17:01:00
【问题描述】:
我有一个表,其中包含一个简单的 int id 列,SQL Server 中的 Identity 自动递增。
实体的 ID 用 @Id 和 @GeneratedValue 注释
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", length = 4, precision = 10, nullable = false)
private Integer id;
在 SQL Server 中,该列被正确设置为 Identity,Seed 和 Increment 等于 1。
当我尝试持久化该实体的实例时,Hibernate 尝试查询 hibernate_sequence 表以获取 ID 值。由于我没有在我的架构中创建该表,我收到了一个错误:
could not read a hi value: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'MySchema.hibernate_sequence'
如果我将生成类型更改为 IDENTITY,一切都会按预期工作
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", length = 4, precision = 10, nullable = false)
private Integer id;
我无法以这种方式更改它,因为我的应用程序将同时在 MS SQL 和 ORACLE 上运行,而后者不支持自动递增的列。
据我所知,如果底层数据库支持 AUTO 类型应该使用自动递增行为,所以我不知道为什么不起作用。
更新:
我花了一些时间,但我能够准确地理解发生了什么。
我正在使用具有以下行为的旧数据库:
- MSSQL:id 生成使用表 IDENTITY
- ORACLE:ID 生成使用触发器。触发器查询并更新存储所有“下一个 id”的自定义表。此表称为 SEQ。
以下是使用一些 id 生成策略的结果:
- AUTO:在 MSSQL 中不起作用,如上所述
- IDENTITY:在 MSSQL 中工作,但不受 Oracle 支持
- “native”:在 MSSQL 中有效,但在 ORACLE 中失败。它失败是因为 Hibernate 激活了它的默认序列策略,它使用 hibernate_sequences.nextval。由于这是一个遗留应用程序,来自 SEQ 表(如上所述)和 hibernate_sequences 的值不同步(该特定表的 SEQ 值为 6120,hibernate_sequences 为 1,这是预期的因为它直到现在才使用)。
所以我需要弄清楚的是一种配置该实体的方法:
- 使用 MSSQL 身份功能 或
- 使用 Oracle 时,不要自动为 ID 变量设置任何值,而是将所有内容留给预先存在的触发器
当我需要插入依赖于主实体(通过外键)的实体时,这可能会导致我在 Oracle 上出现严重问题,因为 Hibernate 不知道哪个 ID 值是由“外部”触发器生成的。
【问题讨论】:
标签: java sql-server database hibernate jpa