[英]Hibernate sequence generator confused by sharing it for multiple entities
我的班级使用的是ID
@Id @Generated(GenerationTime.INSERT) @GeneratedValue private Integer id;
这适用于H2(支持序列),并通过创建帮助程序表hibernate_sequence
解释MySql。 使用这个答案 ,一切都看起来像我想要的方式,特别是对所有表使用单个序列。
有一件事似乎是错误的:帮助程序表中有多行。 我的id
在@MappedSuperclass
声明,在初始化期间, 对于每个具体类,这一行被执行:
insert into hibernate_sequence values ( 1 )
这显然是错误的:每个表都有一行,每个都包含相同的值(最初一个;当更改时,它们都以相同的方式更改,因为SQL update hibernate_sequence set next_val=? where next_val=?
,所以它以相同的方式影响所有行)。
这是无害的,但我想知道:这是一个错误还是我做错了什么?
如果你想让它工作,你现在需要使用其他策略:
@GenericGenerator(
name = "table_generator",
strategy = "org.hibernate.id.enhanced.TableGenerator"
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "table_generator")
那么org.hibernate.id.enhanced.SequenceStyleGenerator
:
我相信hibernate如何初始化共享单行序列表存在问题。
对于hibernare 5.0.6.Final问题的根源在于org.hibernate.boot.internal.InFlightMetadataCollectorImpl
类中
private void processExportableProducers(MetadataBuildingContext buildingContext) {
// for now we only handle id generators as ExportableProducers
final Dialect dialect = getDatabase().getJdbcEnvironment().getDialect();
final String defaultCatalog = extractName( getDatabase().getDefaultNamespace().getName().getCatalog(), dialect );
final String defaultSchema = extractName( getDatabase().getDefaultNamespace().getName().getSchema(), dialect );
for ( PersistentClass entityBinding : entityBindingMap.values() ) {
if ( entityBinding.isInherited() ) {
continue;
}
// ***************************************************************************
// For Instance, it does not filter out the same entityBinding.getIdentifier()
// and make initialization multiple time
// ***************************************************************************
handleIdentifierValueBinding(
entityBinding.getIdentifier(),
dialect,
defaultCatalog,
defaultSchema,
(RootClass) entityBinding
);
}
for ( Collection collection : collectionBindingMap.values() ) {
if ( !IdentifierCollection.class.isInstance( collection ) ) {
continue;
}
handleIdentifierValueBinding(
( (IdentifierCollection) collection ).getIdentifier(),
dialect,
defaultCatalog,
defaultSchema,
null
);
}
}
假设有一个用@MappedSuperclass
注释的Base
类。 还有A
类和B
类扩展Base
类; 如果注释Id
在外地Base
带班@SequenceGenerator
,各子类Base
共享相同的序列发生器,将increament /数据库它们的ID使用相同的序列 。 这在当然是无害的,但会导致ids的数字难看:
@MappedSuperclass
public class Person {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="id_gen")
@SequenceGenerator(name="id_gen", sequenceName="a_seq", allocationSize=1)
private Long id;
}
@Entity
public class A extends Base {
}
@Entity
public class B extends Base {
}
这是他们的ids在添加A,然后B,然后A,然后A:
A{id=1, name='...'}
B{id=2, name='...'}
A{id=3, name='...'}
一种更好的方法是为每个表创建一个新的序列 ,可以通过为不同的子类分配不同的序列生成器来实现:
@MappedSuperclass
public class Person {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="id_gen")
private Long id;
}
@Entity
@SequenceGenerator(name="id_gen", sequenceName="a_seq", allocationSize=1)
public class A extends Base {
}
@Entity
@SequenceGenerator(name="id_gen", sequenceName="b_seq", allocationSize=1)
public class B extends Base {
}
在添加A,然后是B,然后是A时,它们的ID将如下所示:
A{id=1, name='...'}
B{id=1, name='...'}
A{id=2, name='...'}
用@MappedSuperclass注释的类没有自己的表。 只有继承该类的实体才有表。 因此,根据初始化没有错误,因为,每个具体实体的顺序应该是不同的。 所以这不是一个错误,而是预期的行为。
关于更新,如果在SINGLE表中插入记录时所有三行都得到更新,那么肯定存在错误。 但我不确定这是否是您遇到的情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.