使用Oracle序列的Hibernate不使用它

时间:2011-08-24 07:01:03

标签: hibernate sequence id-generation

我已经将hibernate配置为使用oracle序列。使用cache = 20,increment = 1创建序列。

一切正常,hibernate持久化实体。 id值很奇怪:50,51 .... 76,201,202 ... 209,1008,1009,5129,5130 ....

如果我要求序列值(从双重中选择hibernate_sequence.nextval),我得到的值就像2,3,4 ....

如果我打开hibernate sql debug,有时间调用“select from hibernate_sequence.nextval from dual”,但是hibernate分配给ID的号码不会按顺序中继!

@Id
@Column(name = "ID", insertable = false, updatable = false)
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "HIBERNATE_SEQUENCE")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator")
private Long id;

3 个答案:

答案 0 :(得分:33)

这是因为SequenceGenerator实际上不是序列生成器。这是一个序列hi-lo发生器。这意味着第一次调用它时,它从序列中获取下一个值(例如6),然后将该值乘以50并得到结果(300)。下次调用时,它返回301(不进入序列),依此类推,直到达到349.然后它会询问序列的下一个值并获得7,它再次乘以50得到350.我的算法描述可以一个接一个,但你明白了。

如果您停止并启动您的应用程序,它将有间隙。但它比纯序列生成器更有效,因为它只在50代中进行一次数据库调用。

有关详细信息,请参阅http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-enhanced-optimizershttp://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-generator

答案 1 :(得分:6)

我认为你的问题是数据库中ID列的值不是自然序列,而是你看到差距的原因:

一些背景知识:

  • 每次拨打select HIBERNATE_SEQUENCE.nextval from DUAL时,序列的值都会增加。
  • 由于您的序列名称是通用的而不是特定于表格,如果您有多个实体都使用HIBERNATE_SEQUENCE作为id生成器,那么序列中的值将用于所有实体。
  • 如果某个其他应用程序使用HIBERNATE_SEQUENCE,则也会跳过该值。
  • 当您使用CACHE = 20时,Oracle将以20个块的形式获取序列号,然后使用内部缓存返回数字。如果缓存丢失(例如,如果数据库关闭),这可能导致跳过数字。
  • 如果从数据库中删除行,则序列值不会更改

例如,请考虑以下情形:

你有两个实体Entity1和Entity2使用HIBERNATE_SEQUENCE作为ID生成器:

  1. 当前HIBERNATE_SEQUENCE值为100
  2. 插入Entity1(使用返回101的HIBERNATE_SEQUENCE)
  3. 插入Entity2(使用返回102的HIBERNATE_SEQUENCE)
  4. 插入Entity2(使用返回103的HIBERNATE_SEQUENCE)
  5. 删除ID为103的Entity2
  6. 您手动执行select HIBERNATE_SEQUENCE.nextval from DUAL(返回104)
  7. 插入Entity1(使用返回105的HIBERNATE_SEQUENCE)
  8. 插入Entity2(使用返回106的HIBERNATE_SEQUENCE)
  9. 所以最后你会:

    • 具有ID(101,105)的实体1
    • 具有ID(102,106)的实体2

    解释了差距。

    编辑:

    即使@SequenceGenerator被设置为使用SequenceGenerator而不是SequenceHiLoGenerator(正如JB Nizet指出的那样,我认为这是间隙的更好解释),生成的ID存在差距通过序列是常见的事情。

答案 2 :(得分:0)

CREATE SEQUENCE SEQ_SEQUENCENAME INCREMENT BY 1 START WITH 1 MINVALUE 1;
grant all on SEQ_SEQUENCENAME to public;

@Id
@Column(name = "ID", unique = true, nullable = false)
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "SEQ_SEQUENCENAME")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator")
private int Id;