Hibernate with Oracle 序列不使用它

发布于 2024-12-01 09:15:09 字数 603 浏览 0 评论 0 原文

我已将 hibernate 配置为使用 oracle 序列。序列是使用缓存 = 20、增量 = 1 创建的。

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

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

如果我打开hibernate sql调试,有时会调用“select 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;

I have configured hibernate to use oracle sequence. Sequence is created with cache=20, increment=1.

All works fine, hibernate persisting entities. The id value is strange: 50,51....76,201,202...209,1008,1009,5129,5130 ....

If I ask for sequence value (select hibernate_sequence.nextval from dual) I get value like 2,3,4 ....

If I turn on hibernate sql debug, there is time to time call "select hibernate_sequence.nextval from dual" but number assigned by hibernate to ID doesn't relay on sequence!

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

丑疤怪 2024-12-08 09:15:09

这是因为 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 了解详细信息。

This is because the SequenceGenerator is not really a sequence generator. It's a sequence hi-lo generator. This means that the first time it's invoked, it gets the next value from the sequence (6 for example), then multiplies this value by 50 and gives you the result (300). The next time it's invoked, it returns 301 (without going to the sequence), and so on until it reaches 349. Then it asks the sequence for the next value and obtains 7, which it multiplies by 50 again to give you 350. My algorithm description could be off by one, but you get the idea.

If you stop and start your application, it will thus have gaps. But it's more efficient than a pure sequence generator because it only makes a database call once in 50 generations.

See http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-enhanced-optimizers and http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-generator for details.

太傻旳人生 2024-12-08 09:15:09

我认为您的问题是数据库中 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(使用 HIBERNATE_SEQUENCE)返回 101)
  3. 插入 Entity2(使用返回 102 的 HIBATE_SEQUENCE
  4. )插入实体 2(使用 HIBERNATE_SEQUENCE 返回 103)
  5. 删除 ID 为 103 的实体 2
  6. 您手动执行 select HIBERNATE_SEQUENCE.nextval from DUAL(返回 104)
  7. 插入实体 1(使用返回 105 的 HIBERNATE_SEQUENCE)
  8. 实体 2被插入(使用HIBERNATE_SEQUENCE返回106)

因此,最后您将得到:

  • Entity1 的 ID 为 (101, 105)
  • Entity2 的 ID 为 (102, 106),

这解释了这些差距。

编辑:

即使 @SequenceGenerator 设置为使用 SequenceGenerator 而不是 SequenceHiLoGenerator (正如 JB Nizet 所指出的,我认为这是对差距的更好解释) ,序列生成的 ID 中的缺口是常见的情况。

I take it that your question is that the values of the ID column in the database are not a natural sequence, but why you are seeing gaps:

A bit of background:

  • Every time you call select HIBERNATE_SEQUENCE.nextval from DUAL the value of the sequence is increased.
  • As your sequence name is generic rather than specific to the table, if you've got multiple entities which all use the HIBERNATE_SEQUENCE as id generator, then the values from the sequences are used in all entities.
  • If some other application uses HIBERNATE_SEQUENCE, then the value is skipped as well.
  • As you are using CACHE=20, Oracle will grab sequence numbers in blocks of 20 and then use an internal cache to return the numbers. This can lead to numbers being skipped if the cache is lost (e.g. if the DB is shut down).
  • If rows are deleted from your database, the sequence value does not change

For example, consider the following scenario:

You've got two entities Entity1 and Entity2 using HIBERNATE_SEQUENCE as the ID generator:

  1. Current HIBERNATE_SEQUENCE value is 100
  2. An Entity1 is inserted (uses HIBERNATE_SEQUENCE which returns 101)
  3. An Entity2 is inserted (uses HIBERNATE_SEQUENCE which returns 102)
  4. An Entity2 is inserted (uses HIBERNATE_SEQUENCE which returns 103)
  5. The Entity2 with ID 103 is deleted
  6. You manually execute select HIBERNATE_SEQUENCE.nextval from DUAL (returns 104)
  7. An Entity1 is inserted (uses HIBERNATE_SEQUENCE which returns 105)
  8. An Entity2 is inserted (uses HIBERNATE_SEQUENCE which returns 106)

So at the end of it you'll have:

  • Entity1 with IDs (101, 105)
  • Entity2 with IDs (102, 106)

which explains the gaps.

EDIT:

Even if the @SequenceGenerator were setup to use the SequenceGenerator rather than the SequenceHiLoGenerator (as pointed out by JB Nizet, which I think is a better explanation for the gaps), gaps in IDs generated by sequences are a common occurrence.

南汐寒笙箫 2024-12-08 09:15:09
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;
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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文