[英]JPA GenerationType.AUTO not considering column with auto increment
I have a table with a simple int id column with Identity auto increment in SQL Server. 我有一个表与一个简单的int id列在SQL Server中具有标识自动增量。
The entity's Id is annotated with @Id
and @GeneratedValue
实体的Id使用@Id
和@GeneratedValue
注释
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", length = 4, precision = 10, nullable = false)
private Integer id;
In SQL Server the column is properly set as Identity with Seed
and Increment
equals to 1. 在SQL Server中,该列已正确设置为Identity with Seed
, Increment
等于1。
When I try to persist an instance of this entity, Hibernate tries to query the hibernate_sequence table to obtain the ID value. 当我尝试持久化该实体的实例时,Hibernate尝试查询hibernate_sequence表以获取ID值。 Since I haven't created that table in my schema I'm getting an error: 由于我没有在我的架构中创建该表,我收到一个错误:
could not read a hi value: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'MySchema.hibernate_sequence'
If I change the generation type to IDENTITY everything works as expected 如果我将生成类型更改为IDENTITY,一切都按预期工作
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", length = 4, precision = 10, nullable = false)
private Integer id;
I cannot change it this way, since my App will run both on MS SQL and ORACLE, and the latter does not support auto incremented columns. 我无法以这种方式更改它,因为我的应用程序将在MS SQL和ORACLE上运行,后者不支持自动增量列。
As far as I know the AUTO type should use the auto increment behaviour if the underlying database has support to it, so I don't know why is not working. 据我所知,如果底层数据库对它有支持,AUTO类型应该使用自动增量行为,所以我不知道为什么不工作。
UPDATE: 更新:
It took me some time but I was able to understand exactly what is going on. 我花了一些时间,但我能够准确理解发生了什么。
I am working with legacy databases with the following behaviours: 我正在使用具有以下行为的旧数据库:
Here is the outcome of using some id generation strategies: 以下是使用一些id生成策略的结果:
So what I need to figure out is a way to configure that entity to: 所以我需要弄清楚的是将该实体配置为:
This can cause me serious issues on Oracle when I need to insert entities that depend on the main entity (via foreign key), because Hibernate won't know which ID value was generated by the "external" trigger. 当我需要插入依赖于主实体的实体(通过外键)时,这可能会导致Oracle出现严重问题,因为Hibernate不会知道“外部”触发器生成了哪个ID值。
I had a similar problem and found this information (deeper explained in here ). 我遇到了类似的问题并找到了这些信息 ( 这里有更深入的解释)。
Adding this property into my persistence.xml file fixed the issue: 将此属性添加到我的persistence.xml文件中可修复此问题:
<property name="hibernate.id.new_generator_mappings" value="false" />
Orcale 12c supports IDENTITY and SQL SERVER 2012 supports SEQUENCES. Orcale 12c支持IDENTITY,SQL SERVER 2012支持SEQUENCES。 I believe a SEQUENCE is always a better choice than an IDENTITY . 我相信SEQUENCE总是比IDENTITY更好的选择 。 IDENTITY disables batching and SEQUENCES allow you to provide optimizers, such as the pooled-lo optimization strategy . IDENTITY禁用批处理,SEQUENCES允许您提供优化程序,例如池化优化策略 。
This is how the actual identifier generator is chosen for the configured GenerationType value: 这是为配置的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";
}
If you use the new identifier generators : 如果您使用新的标识符生成器 :
properties.put("hibernate.id.new_generator_mappings", "true"); properties.put(“hibernate.id.new_generator_mappings”,“true”);
The AUTO will actually use a SequenceStyleGenerator and where the database doesn't support sequences, you end up using a TABLE generator instead (which is a portable solution but it's less efficient than IDENTITY or SEQUENCE). AUTO实际上将使用SequenceStyleGenerator,并且数据库不支持序列,您最终会使用TABLE生成器(这是一个可移植的解决方案,但它的效率低于IDENTITY或SEQUENCE)。
If you use the legacy identifier generators, you then end up with the "native" generation strategy, meaning: 如果您使用遗留标识符生成器,则最终会使用“本机”生成策略,这意味着:
public Class getNativeIdentifierGeneratorClass() { if ( supportsIdentityColumns() ) { return IdentityGenerator.class; } else if ( supportsSequences() ) { return SequenceGenerator.class; } else { return TableHiLoGenerator.class; } }
If a new Oracle12gDialect is going to be added and it will support IDENTITY, then AUTO might switch to IDENTITY rather than SEQUENCE, possibly breaking your current expectations. 如果要添加新的Oracle12gDialect并且它将支持IDENTITY,那么AUTO可能会切换到IDENTITY而不是SEQUENCE,可能会破坏您当前的期望。 Currently there is no such dialect available so on Oracle you have SEQUENCE and in MSSQL you have IDENTITY. 目前没有这样的方言,所以在Oracle上有SEQUENCE,在MSSQL中你有IDENTITY。
Conclusion: 结论:
Try it like this: 试试这样:
@Id
@GenericGenerator(name = "native_generator", strategy = "native")
@GeneratedValue(generator = "native_generator")
private Long id;
If your legacy system uses a table for generating sequence values and there was no hilo optimization ever used you can use a table identifier generator: 如果旧系统使用表生成序列值,并且没有使用过hilo优化,则可以使用表标识符生成器:
@Id
@GeneratedValue(generator = "table", strategy=GenerationType.TABLE)
@TableGenerator(name = "table", allocationSize = 1
)
private Long id;
You can also use the JPA table generator, just make sure you configure the right optimizer. 您也可以使用JPA表生成器,只需确保配置正确的优化器。 For more info check my Hibernate tutorial 有关更多信息,请查看我的Hibernate教程
because 因为
@GeneratedValue(strategy = GenerationType.AUTO)
use SequenceStyleGenerator
by default in earlier versions 在早期版本中默认使用SequenceStyleGenerator
you have to look at this https://hibernate.atlassian.net/browse/HHH-11014 你必须看看这个https://hibernate.atlassian.net/browse/HHH-11014
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.