2009-11-30 195 views
10

我的主鍵實體看起來像下面JPA主鍵自動生成

@GeneratedValue(strategy= GenerationType.TABLE) 
private Long id; 

當我運行,我得到錯誤

無法獲得或更新下一個值;嵌套的例外是org.hibernate.exception。 SQLGrammerException:無法獲得或更新下一個值

但是當我剛剛更改爲

@GeneratedValue 
private Long id; 

沒有錯誤拋出。我想在每個表上爲oracle db生成唯一的主鍵。

回答

28

@GeneratedValue(strategy=GenerationType.TABLE)告訴JPA提供者在將新創建的實體插入數據庫時​​使用表來獲取ID。

當使用Hibernate作爲提供者時,這會產生一個表hibernate_sequences,它有兩列:實體名稱和已經分配給該實體的最大身份。在這裏,看起來Hibernate沒有成功從您的實體獲取下一個ID,但很難說明原因,因爲您沒有提供足夠的信息。

那麼,您能否提供完整的堆棧跟蹤?此外,請將hibernate.show_sql屬性設置爲true,並設置正確的日誌級別log4j.logger.org.hibernate.SQL=DEBUG。如果可能的話,加入日誌到你的問題。

也許只是檢查您是否爲Oracle配置了正確的hibernate.dialect。實際上,如果可能的話,加入你的休眠配置。 PS:使用Oracle生成PK的「傳統」方法是使用序列(您可以讓Hibernate使用GenerationType.AUTO或使用SEQUENCE強制使用SEQUENCE來推測您的數據庫類型的最佳策略),但我會假設您需要結果數據結構是數據庫不可知的。如果沒有,我會建議去替代序列。

編輯:回答評論從OP約GenerationType.AUTO。事實上,默認值是一個叫做hibernate_sequence的單一全局序列,這可能是一個問題。但是,如下所示的設置,您可以使用GenerationType.AUTO,仍然控制的情況下,序列的名稱,其中數據庫採用序列:

@Id 
@GeneratedValue(strategy=GenerationType.AUTO, generator="my_entity_seq_gen") 
@SequenceGenerator(name="my_entity_seq_gen", sequenceName="MY_ENTITY_SEQ") 
private long id; 

換句話說,你可以使用使用不同的序列名稱爲每個表沒有失去可移植性。

+2

如果我把GenerationType.Auto,它將使用全局增量數,意味着我所有的實體將增加相同的數字。代碼運行正常,但它會用完增量數字嗎? – cometta 2009-11-30 04:53:54

+0

@Pascal:如果我們提供了一個SequenceGenerator,它是否有助於將Startegy指定爲AUTO? – Nrj 2009-11-30 05:36:51

+0

@Nrj實際上,如果你使用'AUTO'並且數據庫使用序列,'@ SequenceGenerator'將有助於控制序列的名稱。但是,如果數據庫不存在,它將被「忽略」(例如使用HSQLDB)。所以,與'SEQUENCE'不同,這是可移植的。 – 2009-11-30 05:49:52

7

有自動生成4個策略JPA:

  • 自動
  • 身份
  • 序列

對於Oracle自動生成主鍵註釋,序列和表是你的選擇。基本邏輯是首先定義一個發生器,分別使用@SequenceGenerator@TableGenerator,然後在@GeneratedValue處使用發生器作爲屬性。

這是如何使用序列的策略的示例:

@Id 
    @SequenceGenerator(name="SEQ_GEN", sequenceName="SEQ_JUST_FOR_TEST", allocationSize=1) 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_GEN") 
    private long id; 

下面是如何使用表策略的示例:

@Id 
    @TableGenerator(name="TABLE_GEN",table="T_GENERATOR", pkColumnName = "GEN_KEY", pkColumnValue = "MONITOR2012.T_JUST_FOR_TEST", valueColumnName = "GEN_VALUE", initialValue = 1, allocationSize = 1) 
    @GeneratedValue(strategy = GenerationType.TABLE, generator="TABLE_GEN") 
    private long id; 

如果@GeneratedValue註解沒有指定發生器,選擇將留給JPA實施。

如果您正在使用現有表的數據庫,請在運行應用程序之前確保數據庫中定義的序列或表。 表生成器還需要您在@GeneratedValue註釋正常工作之前向表中插入一行。

這裏是關於how to configure primary key auto generation in JPA for Oracle database的教程。