我的课程使用像
这样的ID@Id @Generated(GenerationTime.INSERT) @GeneratedValue private Integer id;
这适用于H2(支持序列),并通过创建帮助程序表hibernate_sequence
来解释MySql。使用this answer,一切看起来都像我想要的那样,特别是对所有表使用单个序列。
有一件事似乎是错误的:帮助程序表中有多行。我的id
在@MappedSuperclass
中声明,在初始化期间,为每个具体类执行此行:
insert into hibernate_sequence values ( 1 )
这显然是错误的:每个表都有一行,每个包含相同的值(最初一个;当更改时,它们都以相同的方式更改,因为SQL为update hibernate_sequence set next_val=? where next_val=?
,因此它会影响所有行以相同的方式)。
这是无害的,但我想知道:这是一个错误还是我做错了什么?
答案 0 :(得分:4)
如果你想让它成功,你现在需要使用其他策略:
@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
);
}
}
答案 1 :(得分:0)
使用@MappedSuperclass注释的类没有自己的表。只有继承该类的实体才有表。因此,根据初始化没有错误,因为,每个具体实体的顺序应该是不同的。所以这不是一个错误,而是预期的行为。
关于更新,如果在SINGLE表中插入记录时所有三行都得到更新,那么肯定存在错误。但我不确定这是否是您遇到的情况。
答案 2 :(得分:0)
假设有Base
类注释@MappedSuperclass
。还有A
和B
类扩展Base
类;如果您使用Id
在Base
类中注释@SequenceGenerator
字段,则Base
的所有子类共享相同的序列生成器,并将增加/使用相同的序列在数据库中为他们的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 {
}
这是他们的ID在添加A,然后是B,然后是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='...'}