我有一个表,其中有一个简单的 int id 列,在 SQL Server 中具有身份自动增量。
实体的 Id 注释为@Id
and @GeneratedValue
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", length = 4, precision = 10, nullable = false)
private Integer id;
在 SQL Server 中,该列已正确设置为 IdentitySeed
and 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 类型应该使用自动增量行为,所以我不知道为什么不起作用。
UPDATE:
我花了一些时间,但我能够准确地理解发生了什么。
我正在使用具有以下行为的遗留数据库:
- MSSQL:id 生成使用表 IDENTITY
- ORACLE:id 生成使用触发器。触发器查询并更新存储所有“下一个 id”的自定义表。该表称为 SEQ。
以下是使用一些 id 生成策略的结果:
- AUTO:在 MSSQL 中不起作用,如上所述
- IDENTITY:适用于 MSSQL,但不受 Oracle 支持
- “native”:在 MSSQL 中有效,但在 ORACLE 中失败。它失败是因为 Hibernate 激活了它的默认序列策略,该策略使用 hibernate_sequences.nextval。由于这是一个遗留应用程序,因此 SEQ 表中的值(如上所述)和休眠序列不同步(该特定表的 SEQ 值是 6120,hibernate_sequences' 是 1,这是预期的,因为直到现在才使用它)。
所以我需要找出一种将该实体配置为的方法:
- 使用 MSSQL 身份功能
或者
- 使用 Oracle 时,不要自动为 ID 变量设置任何值,而将所有内容留给预先存在的触发器
当我需要插入依赖于主实体(通过外键)的实体时,这可能会导致 Oracle 出现严重问题,因为 Hibernate 不知道哪个 ID 值是由“外部”触发器生成的。