簡體   English   中英

如何強制提交Spring-安全地休眠事務

[英]How to force commit Spring - hibernate transaction safely

我們在Web應用程序中使用spring和hibernate:該應用程序有一個購物車,用戶可以在其中放置物品。 為了保留要在不同登錄名之間查看的項目,購物車中的項目值存儲在表中。 提交購物車時,如果需要生成訂單號,則商品將保存到其他表格中。

當我們將值插入表中以獲取訂單號時,我們用於獲取最大訂單號並為其添加+1。 我們使用的是Spring事務管理器和休眠模式,在代碼流中,我們獲得了訂單號並更新了休眠對象以保存訂單號值。 調試時,我注意到只有在發出完整交易時,才會插入訂單號實體bean。

這里的問題是,當我們同時向服務器提交兩個請求,使用相同的訂單號,並且僅插入一個請求數據時。 無法插入另一個唯一的請求值。 表中的訂單號是唯一的。

我注意到在調試持久層時,即使在發出會話刷新session.flush()之后也沒有將其插入數據庫中

它僅在spring事務結束時更新內存並將數據插入db中。 我試圖明確發出交易承諾

session.getTransaction().commit();

這會立即將值插入數據庫,但在進一步的代碼流上顯示了無法啟動事務的消息。

非常感謝您的幫助。

補充:我使用的Oracle數據庫。 該表有一個唯一的序列號,並且訂單號也映射到該表。

我將使用觸發器設置訂單號,該觸發器將在與購物車插入一個交易的同一筆交易中運行。

保存購物車后,要查看更新的訂單數,您必須致電:

session.refresh(cart);

該計數不應該由Hibernate管理( insertable/updatable = false@Transient )。

您的第一個問題是,當多個線程執行相同的邏輯時,圍繞數字生成進行串行訪問。 如果您可以使用Oracle序列,則將保證在數據庫級別自動解決該問題,因為保證序列可以在調用多次后返回唯一值。 但是,由於現在需要在服務器端對此進行管理,因此您將需要在事務生成邊界周圍的數字生成邏輯(選擇max並以1為增量)周圍使用同步機制。 您可以使Service方法同步(您的服務類將是Singleton,由Spring管理),並聲明其周圍的事務邊界。 但是請注意,這會影響性能,通常不利於可伸縮性。

另一個選擇可能是此方法的變體-將要分配的ID存儲在帶有“ currentVal”列的單獨表中,並使用悲觀鎖獲取下一個數字。 這樣,主表將沒有任何大鎖。 這樣,在主要實體創建事務完成時,將為序列生成器代碼保留一個鎖。 這些技術背后的主要思想是序列化對序列生成器的訪問並保持鎖定,直到主要實體事務提交為止。 還應盡可能延遲數字生成器。

如果在設計中使用觸發器,則@Vlad建議的解決方案是一個很好的解決方案。

關於沖洗行為的問題,SQL在沖洗調用時發送到數據庫,但是只有在聲明式提交事務或調用手動提交后,數據才提交。 但是,根據事務的隔離性,事務可以看到要更改的數據,而其他事務則看不到。

請按照下列步驟操作:-,1)在不同的服務類中創建具有傳播REQUIRES_NEW的服務方法。 2)以這種新方法移動您的代碼(無論您想刷新到db的所有代碼)。 3)從現有的api調用此方法(由於在春季使用了代理,我們必須從不同的類調用此新的服務方法,否則REQUIRES_NEW將無法確保您的刷新數據)。

暫無
暫無

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

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