2016-11-30 54 views
0

我有使用Hibernate寫入Oracle表的代碼。它使用SequenceGenerator生成唯一的ID。假設我在數據庫中有ID從1到40。會發生什麼情況是,如果有任何用戶從表中刪除,它會在表中的ID中留下空隙(例如,id = 24)。然後,當創建新用戶時,新用戶的ID由Hibernate設置爲24.Hiberate生成@GeneratedValue,導致UniqueConstraint違反

現在有一個問題,因爲緊接着的下一個新用戶獲得id = 25,這會導致出現UniqueConstraint異常。

有什麼我做錯了嗎?我如何讓Hibernate停止生成表中已經存在的序列值?

@Entity 
@Table(name="User") 
public class User { 
    @Id 
    @SequenceGenerator(name="UserGen", sequenceName="UserSeq") 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="UserGen")  
    private Integer id; 

    @Column(length=64, unique=true) 
    private String username; 
... 

下面是Oracle的序列信息:

CREATED 31-OCT-16 
LAST_DDL_TIME 31-OCT-16 
SEQUENCE_OWNER USERSERVICE 
SEQUENCE_NAME USERSEQ 
MIN_VALUE 1 
MAX_VALUE 9999999999999999999999999999 
INCREMENT_BY 1 
CYCLE_FLAG N 
ORDER_FLAG N 
CACHE_SIZE 20 
LAST_NUMBER 81 
PARTITION_COUNT 
SESSION_FLAG N 
KEEP_VALUE N 
+1

您的診斷錯誤。該序列不關心表中ID的空位。這只是一個序列,每次請求下一個值時都會遞增。您只需用最小值初始化您的序列,這會使生成器生成已在表中用作ID的值。 –

+0

你說得對。我確實診斷錯了。真正的問題是這樣的:http://stackoverflow.com/questions/9861416/hibernate-generates-negative-id-values-when-using-a-sequence – leontp587

回答

0

你必須定義你的SequenceGenerator具有相同的allocationSize爲您的序列INCREMENT_BY值。

@SequenceGenerator(name="UserGen", sequenceName="UserSeq", allocationSize = 1) 

我遇到這個問題之前(在PostgreSQL的),最終我只是把它改爲@GeneratedValue(strategy = GenerationType.IDENTITY)和完全刪除SequenceGenerator S,因爲他們沒有指定的時候已經用作插入默認值。當序列增量大小爲1時,性能略有提升,因爲Hibernate通過SequenceGenerator手動調用序列,並使用一個可以省略的額外查詢。

+0

同意。分配大小= 1。這對我有效。 需要注意的是,對於Oracle。不支持GenerationType.IDENTITY: 根據:http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing 「身份排序使用數據庫中的特殊IDENTITY列來允許數據庫自動爲其分配一個ID對象,當它的行被插入時,許多數據庫(如MySQL,DB2,SQL Server,Sybase和Postgres)都支持標識列,Oracle不支持IDENTITY列,但可以通過使用序列對象和觸發器來模擬它們。 – leontp587