序列问题为啥两个实体在使用 hbm2ddl 生成模式时共享相同的序列?

Posted

技术标签:

【中文标题】序列问题为啥两个实体在使用 hbm2ddl 生成模式时共享相同的序列?【英文标题】:Issue with sequence why two entity are sharing the same sequence when generating schema with hbm2ddl ?序列问题为什么两个实体在使用 hbm2ddl 生成模式时共享相同的序列? 【发布时间】:2011-10-16 05:24:42 【问题描述】:

我在基于休眠的应用程序中使用hbm2ddl 来生成数据库模式。 hibernate.hbm2ddl.auto 属性的值为create-drop

我正在为我的 POJO 类使用 @Entity 注释。

@Entity 
public class testTable1 
     @Id     
     @GeneratedValue(strategy = GenerationType.SEQUENCE)
     Long id; 


@Entity 
public class testTable2 
     @Id     
     @GeneratedValue(strategy = GenerationType.SEQUENCE)
     Long id; 

但是,在执行代码时,我不断获得递增的 Id 值。例如对于 2 个表,ID(即 Prim Key)应该以 1 开头。但是在 Table 1 中插入记录后,序列从 Table 2 的下一个值开始。对于表 2,它应该从 1 重新开始。 我试过GenerationType.SEQUENCEGenerationType.AUTO。没有任何效果:-(

【问题讨论】:

【参考方案1】:

当没有按照 JPA 规范指定的生成器提供时,您使用的是 hibernate 默认提供的全局序列生成器。要拥有一个私有生成器,您应该使用注释@SequenceGenerator 声明一个私有生成器,并设置@GeneratedValue 注释的generator 属性

从javadoc中提取

@GeneratedValue (可选)指定使用的主键生成器的名称 在 SequenceGenerator 或 TableGenerator 注释中。

默认为持久性提供者提供的 id 生成器。

SequenceGenerator 这个注解定义了一个主键生成器,当一个 生成器元素是为 GeneratedValue 注释指定的。一种 序列生成器可以在实体类或 主键字段或属性。生成器名称的范围是 全局到持久性单元(跨所有生成器类型)。

例子:

@SequenceGenerator(name="EMP_SEQ", sequenceName="private_sequence")

Hibernate 建议新项目使用 hibernate.id.new_generator_mappings=true,因为新生成器更高效且更接近 JPA 2 规范语义

Section 1.3. Properties2.2.3. Mapping identifier properties

完整示例

@Entity
@SequenceGenerator(name="PRIVATE_SEQ", sequenceName="private_sequence")
public class test 

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="PRIVATE_SEQ")
    Long id;

【讨论】:

是的,我想补充一点,如果你想设置初始值和分配大小,你需要包括 hibernate.id.new_generator_mappings=true。然后你只需要像这样使用@SequenceGenerator:@SequenceGenerator(initialValue=1, allocationSize=1, name="PRIVATE_SEQ", sequenceName="private_sequence") 或任何你需要给出的值。 @BreakingBenjamin 我可以像你上面所说的那样为多个实体使用相同的序列生成器,并在每个实体中获得统一的独占 id 值吗?我的意思是每个实体 id 将从 1 开始并以 1 递增。【参考方案2】:

Hibernate 5.2 中,

我尝试过 Joel Hudon 的回答,但不知道为什么它不起作用。

我找到了一些较短的代码来解决它。

3.2. The annotated entity Java class

@Id
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment")
public int id;

它可以给出唯一的序列号。

希望对你有帮助。

【讨论】:

【参考方案3】:
 @Entity
    public class MyEntity2 
        
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="myentity2_seq")
        @SequenceGenerator(name = "myentity2_seq",sequenceName = "myentity2_seq_table")
        private int id;

    @Column(length = 100)
    private String name;
//setters & getters ...

在数据库中,它会创建myentity2_seq_table表来维护id。我们可以在 SequenceGenerator 中使用 initialValue = 100, allocationSize = 10 来自定义建表。

【讨论】:

以上是关于序列问题为啥两个实体在使用 hbm2ddl 生成模式时共享相同的序列?的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate 根据实体类自动生成表问题

如何让hibernate hbm2ddl生成带分号的SQL?

为啥 liquibase 总是使用自己的序列?

为啥人们说使用随机数生成器时存在模偏差?

为啥 hbm2ddl.SchemaExport 不在此处运行?

实体类为啥要序列化