我有一个带有简单int id列的表,在SQL Server中具有Identity auto increment。
实体的ID已注明@Id
和@GeneratedValue
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", length = 4, precision = 10, nullable = false)
private Integer id;
在SQL Server中,该列已正确设置为标识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类型应该使用自动增量行为,所以我不知道为什么不工作。
更新:
我花了一些时间,但我能够准确理解发生了什么。
我正在使用具有以下行为的旧数据库:
以下是使用一些id生成策略的结果:
所以我需要弄清楚的是将该实体配置为:
当我需要插入依赖于主实体的实体(通过外键)时,这可能会导致我在Oracle上出现严重问题,因为Hibernate不知道" external&#生成了哪个ID值34;触发。
答案 0 :(得分:9)
我遇到了类似的问题并发现了information(here中更深入解释)。
将此属性添加到我的persistence.xml文件中修复了问题:
<property name="hibernate.id.new_generator_mappings" value="false" />
答案 1 :(得分:6)
Orcale 12c支持IDENTITY,SQL SERVER 2012支持SEQUENCES。我相信SEQUENCE is always a better choice than an IDENTITY。 IDENTITY禁用批处理,SEQUENCES允许您提供优化程序,例如pooled-lo optimization strategy。
这是为配置的GenerationType值选择实际标识符生成器的方式:
switch ( generatorEnum ) {
case IDENTITY:
return "identity";
case AUTO:
return useNewGeneratorMappings
? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()
: "native";
case TABLE:
return useNewGeneratorMappings
? org.hibernate.id.enhanced.TableGenerator.class.getName()
: MultipleHiLoPerTableGenerator.class.getName();
case SEQUENCE:
return useNewGeneratorMappings
? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()
: "seqhilo";
}
如果您使用new identifier generators:
properties.put(&#34; hibernate.id.new_generator_mappings&#34;,&#34; true&#34;);
AUTO实际上会使用SequenceStyleGenerator,而数据库不支持序列,你最终会使用TABLE生成器(这是一个便携式解决方案,但它的效率低于IDENTITY或SEQUENCE)。
如果您使用旧标识符生成器,则最终会使用&#34; native&#34;生成策略,意思是:
public Class getNativeIdentifierGeneratorClass() {
if ( supportsIdentityColumns() ) {
return IdentityGenerator.class;
}
else if ( supportsSequences() ) {
return SequenceGenerator.class;
}
else {
return TableHiLoGenerator.class;
}
}
如果要添加新的Oracle12gDialect并且它将支持IDENTITY,那么AUTO可能会切换到IDENTITY而不是SEQUENCE,可能会破坏您当前的期望。目前没有这样的方言,所以在Oracle上你有SEQUENCE,在MSSQL中你有IDENTITY。
<强>结论:强>
试试这样:
@Id
@GenericGenerator(name = "native_generator", strategy = "native")
@GeneratedValue(generator = "native_generator")
private Long id;
如果旧系统使用表格生成序列值,并且没有使用过hilo优化,则可以使用表格标识符生成器:
@Id
@GeneratedValue(generator = "table", strategy=GenerationType.TABLE)
@TableGenerator(name = "table", allocationSize = 1
)
private Long id;
您也可以使用JPA表生成器,只需确保配置正确的优化器。有关详细信息,请查看我的Hibernate tutorial
答案 2 :(得分:0)
因为
@GeneratedValue(strategy = GenerationType.AUTO)
默认情况下在早期版本中使用SequenceStyleGenerator