2011-08-24 60 views
17

我配置了休眠使用oracle序列。序列創建緩存= 20,增量= 1。休眠與Oracle序列不使用它

所有的工作正常,休眠持久實體。該ID值是奇怪的:50,51 .... 76,201,202 ... 209,1008,1009,5129,5130 ....

如果我問序列值(從雙選擇hibernate_sequence.nextval)我得到值如2,3,4 ....

如果我打開hibernate sql調試,有時間調用「從雙選擇hibernate_sequence.nextval」,但由休眠分配的ID號不會按順序中繼!

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

回答

30

這是因爲SequenceGenerator實際上並不是一個序列生成器。這是一個序列hi-lo發生器。這意味着第一次被調用時,它會從序列中獲得下一個值(例如6),然後將該值乘以50並給出結果(300)。下一次它被調用時,它返回301(不去序列),依此類推,直到達到349.然後它詢問序列中的下一個值並獲得7,再乘以50再給你350. My算法描述可能會被忽略,但你明白了。

如果您停止並開始您的應用程序,它將因此存在差距。但它比純序列發生器更有效率,因爲它只在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

+10

你不必每次增加50。這只是默認設置。使用 @SequenceGenerator(name =「SEQ_ID」,sequenceName =「SEQ_ID」,allocationSize = 1) 僅增加一個。分配大小是關鍵。 – dseibert

+2

反正有沒有用這個? 既然它對我來說是一個很大的問題,讓其他觸發器對這個表使用相同的序列。那麼他們將來可能會打這個數字,對吧? –

+0

看看你上面的評論。使用allocationSize。 –

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被插入(採用HIBERNATE_SEQUENCE返回101)
  3. 一種ENTITY2被插入(使用HIBERNATE_SEQUENCE返回102)
  4. 的ENTITY2被插入(使用HIBERNATE_SEQUENCE返回103)
  5. 的ENTITY2與ID 103被刪除
  6. 您手動執行select HIBERNATE_SEQUENCE.nextval from DUAL(返回104)
  7. 一種ENTITY1被插入(使用HIBERNATE_SEQUENCE返回105)
  8. 的ENTITY2被插入(使用HIBERNATE_SEQUENCE返回106)

因此,在它的端你將有:

  • ENTITY1使用標識(101,105)
  • ENTITY2使用標識(102,106)

這解釋了間隙。

編輯:

即使@SequenceGenerator是設置使用SequenceGenerator而不是SequenceHiLoGenerator(由JB Nizet,我認爲這是對缺口更好的解釋中指出),所產生的標識差距序列是一種常見現象。

1
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;