22

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

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

如果我要求序列值(从 dual 中选择 hibernate_sequence.nextval),我得到的值类似于 2,3,4 ....

如果我打开休眠 sql 调试,有时会调用“select hibernate_sequence.nextval from dual”但是休眠分配给 ID 的数字不会按顺序传递!

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

3 回答 3

34

这是因为 SequenceGenerator 并不是真正的序列生成器。这是一个序列高低生成器。这意味着第一次调用它时,它会从序列中获取下一个值(例如 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了解详情。

于 2011-08-24T07:22:21.833 回答
8

我认为您的问题是数据库中 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)

所以最后你会得到:

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

这解释了差距。

编辑:

即使@SequenceGenerator 设置为使用SequenceGenerator而不是SequenceHiLoGenerator(正如JB Nizet 指出的那样,我认为这是对间隙的更好解释),由序列生成的ID 中的间隙是常见的。

于 2011-08-24T07:22:42.047 回答
-2
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;
于 2016-07-28T04:14:03.353 回答