簡體   English   中英

如何鎖定事務以讀取行然后在Hibernate中插入?

[英]How to lock a transaction for reading a row and then inserting in Hibernate?

我有一個帶有名稱和name_count的表。 因此,當我插入新記錄時,我首先檢查該名稱的最大name_count是多少。 然后,我插入具有最大+ 1的記錄。工作得很好...除了mysql 5.1和hibernate 3.5,默認情況下,讀取操作不遵守事務邊界。 其中兩個具有相同名稱的插入可以同時發生,並以相同的name_count結束,這完全搞砸了我的應用程序!

不幸的是,在某些特定情況下,上述情況實際上相當普遍。 那我該怎么辦? 我假設我可以進行悲觀鎖,其中我讀取的任何行都被鎖定以供進一步讀取,直到我提交或回滾事務為止。 或者我可以使用版本列進行樂觀鎖定,該列會自動不斷嘗試直到沒有沖突?

什么是針對我的情況的最佳方法,如何在Hibernate 3.5和mysql 5.1中指定它? 上表很大,經常訪問。

這就是為什么大多數人使用SEQUENCE創建唯一數字的原因。 就是說,您必須要做的就是鎖定整個表( LOCK TABLES )。 問題:您必須鎖定所需的所有表(即Hibernate可能碰到的任何表),否則會出錯。 接下來,您必須解鎖表,並與事務的其余部分同步進行這兩項操作。

我希望這能使您了解人們為什么使用序列:它們有一些小缺陷,例如缺口,但是其他所有問題都會更糟。

[編輯]您可以定義一個序列,然后使用本機SQL查詢獲取下一個值。 您可以嘗試定義一個序列生成器(請參閱docs ),但也許僅在ID字段上允許映射。

關於“ 2億個名稱”:只要數據庫可以存儲該數字,您還可以在其上定義一個序列。

關於“基於行的鎖定”:您打算鎖定哪一行? 一個最大的值? 我不確定如果鎖定它, max()運算符將停止。 您可以嘗試的是一個觸發器 由於觸發器是原子觸發器,因此在運行時沒有人可以插入一行。 但是觸發器很難維護。

MySQL不支持序列,因此應對其進行仿真。 這是一個有趣的食譜: http : //forums.mysql.com/read.php?61,143867,194058#msg-194058

請注意,表類型為MyISAM,以不遵守事務並發性,並在每個請求上返回下一個計數器值。

如果要使其與數據庫無關(避免序列),而不必在插入之前運行max()函數,請嘗試使用guid代替:

/**
 * The unique id. This id is generated this object is persited. The id is a 32 character UUID.
 * This gives each entity a completely unqique identifier. This is completely unique across all
 * databases, jvms and entities.
 */
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(length = 32, name = EntityObject.Columns.ID)
@DocumentId
private String id;

這還有一個好處,即主鍵在數據庫中的每個表中都是唯一的,這非常適合分布式數據庫。

我們已經在許多數據庫中使用了它,我們可以輕松地在它們之間移動。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM