2017-08-28 108 views
0

我正在使用具有使用ECache配置的休眠功能的broadleaf演示應用程序。我也有一個外部應用程序,它直接與相同的數據庫進行交互。 當我使用外部應用程序更新數據庫時,我的broadleaf應用程序不知道這些更改會在創建新實體時拋出重複的主鍵。我試圖通過定期清除休眠緩存來解決這個問題,這使得休眠從頭開始構建緩存,因此一切都會同步。 我正在使用以下代碼清除二級緩存。無法清除休眠緩存

Cache cache = sessionFactory.getCache(); 
String entityName = "someName"; 
cache.evictEntityRegion(entityName); 

但是,這似乎並不奏效。

我甚至嘗試使用JMX監聽器手動清除cahche,如visualvm。但這也行不通。我仍然在API中獲得舊的主鍵值。這是因爲只有二級緩存正在被清除而離開一級緩存?我被困在這裏。任何人都可以幫助解決這個問題嗎?

更新: 比方說,我有應用一個。 A使用broadleaf,B使用原始SQL查詢插入到db中。我使用應用程序A創建了幾個訂單,然後使用應用程序B直接在數據庫中插入幾個訂單,並使用max(order_id)+ 1更新SEQUENCE_GENERATOR表。之後,當我嘗試使用應用程序A創建訂單時,它會引發重複的主鍵例外。我試圖調試到問題,我發現IdOverrideTableGenerator仍然給我舊的主鍵。這讓我對二級緩存感到好奇。不是broadleaf使用SEQUENCE_GENERATOR用於啓動主鍵生成引用並在緩存中維護當前狀態?在我的情況下,即使更新SEQUENCE_GENERATOR也不能確保新的唯一主鍵。

+0

max(order_id)方法不起作用。 OrderImpl的默認增量大小爲50。在從應用程序B插入記錄之前,您需要事先預定一批ID(例如,其中50個)。這可以保證應用程序A在它請求另一批次時不會使用任何這些ID,並且它保證應用程序B不會使用運行應用程序A的實例中的任何當前保留的ID。還有一點很重要,那就是有一些鎖定方法,應用程序B的預訂不會意外分享。 – mbvcomeback

+1

不是直接進入數據庫手動插入訂單,而是在Broadleaf一側構建一個API端點,將您的其他系統的訂單轉換爲Broadleaf'Order',然後保持該狀態,這是一種更好的模式。然後,您可以完全避免整個sequence_generator問題,同時可以更好地分離兩個系統。 – phillipuniverse

+0

我同意菲利普。如果您的設計要求允許,最好的辦法是創建一個接受訂單信息並保留訂單的API端點。 – mbvcomeback

回答

2

如果您希望您的實施在運行時識別新實體,則說明您需要對外部導入使用L2高速緩存失效。否則,您將不得不等待緩存區域上配置的TTL過期以便應用程序查看新記錄。

但是,在Broadleaf的情況下,L2緩存與Hibernate如何確定主鍵沒有任何直接關係。 Broadleaf利用表生成器策略以高性能和集羣安全的方式獲取一批ID。您可能會注意到您的模式中有一個名爲SEQUENCE_GENERATOR的表。該表包含已爲不同的域類獲取的各種id範圍。每當Hibernate需要爲插入操作獲取一批新的ID時,它將與該表交互以註冊一個新的ID範圍以檢出。這應該保證羣集中的任何節點都不會嘗試插入具有衝突ID的實體。

對於您的情況,您需要保證外部進程可以以非衝突方式執行插入。爲此,我相信你需要爲外部進程創建一個API來調用它,它將代表該調用進程執行相同的「id checkout」操作。然後,您的導入代碼(可能位於其他地方)將包含一系列可以安全使用的ID。支持您創建的API的代碼應執行與Hibernate通常執行的操作相同的操作,以獲取一批用於實體插入的ID。您可以查看org.hibernate.id.enhanced.TableGenerator獲取這個樣子的例子,併爲您自己的目的創建類似的東西。

+0

我只是想補充一點,並不是所有的框架類都使用hibernate生成器CustomerImpl,但實際上並沒有。它使用IdGenerationService – John

+0

很好的答案。關鍵在於,當您更新數據庫中的記錄時,還需要更新'SEQUENCE_GENERATOR'中的ID範圍。 @約翰是正確的,'BLC_ID_GENERATION'是'CustomerImpl'。 這裏是'BLC_PRODUCT'的MySQL示例。如果還沒有'ProductImpl'鍵,這也適用。你可以在直接插入一組產品後運行這個'SET @id =(SELECT MAX(product_id)+ 1 FROM blc_product); INSERT INTO sequence_generator(ID_NAME,ID_VAL)VALUES('ProductImpl',@id)ON DUPLICATE KEY UPDATE id_val = @id;' – phillipuniverse

+0

@phillipuniverse我已經更新了SEQUENCE_GENERATOR表中的相應實體值。仍然我從IdOverrideTableGenerator獲得舊生成的主鍵。 – amanraj