2013-06-25 54 views
0

刪除之後這是序列靜止投擲IntegrityConstraintViolation:的EclipseLink 2.5持久實體時,記錄從數據庫

  1. App1的:與ID = 1數據庫堅持實體。沒問題。
  2. App2:外部應用程序刪除ID = 1的相同記錄。沒問題。
  3. App1:試圖再次堅持先前被App2刪除的實體,這裏會拋出一個異常說「IntegrityConstraintViolation」,好像記錄仍然在數據庫中,而我插入它兩次,而不是。

問題是,正如我所看到的,EntityManager正在使用緩存來驗證數據庫的完整性。不知何故,即使我打電話

getEM().getEntityManagerFactory().getCache().evictAll(); or getEM().clear();

EntityManager的是保持這個紀錄在高速緩存中不知何故,和我跑出來的有關如何清除高速緩存的想法。一個解決辦法,我發現是從應用1致電:

getEM().remove(entity.class, id);

,並有效地從數據庫和EntityManager的緩存過的記錄。但是,這不是重點,它只能證明它使用緩存進行驗證,但主要問題仍然存在,「我從另一個應用程序中刪除後無法再保留該記錄」。

順便說一句,我也嘗試刷新實體,並沒有工作。它會拋出一個異常,說實體沒有管理。

有人有任何想法如何解決這個問題?

+0

步驟1和3是否使用EntityManager的相同實例執行,或者是否爲每個操作創建新實例? –

+0

你使用持久還是合併?如果它使用樂觀鎖定,請嘗試清除版本字段 – Chris

+0

Hi @DavidLevesque,是的,它對操作,插入和刪除都使用相同的EntityManager。事實上,爲了包含更多信息,發生這種情況的場景是爲幾種方法運行測試用例。我稱之爲App1的是'methodA',App2是Test Class的'tearDown'方法。這種交互發生在幾個方法和'tearDown'方法之間,在這個方法中,所有的測試用例都在數據庫上創建記錄用於測試目的,'tearDown'方法**清理**數據庫,以便下一個測試用例可以在清理時開始執行數據庫。 –

回答

0

終於解決了這個情況,這個版本的EclipseLink 2.5的行爲有點不同於以前的版本,這是其中的一個區別。問題是,我是在「TEARDOWN()」執行該線的TestClass的方法:

em.CreateQuery("delete from mytable").executeUpdate(); 

清潔在數據庫中的表。即使這條線有效地從數據庫中刪除記錄,如果你使用的是同一個EntityManager,那麼無論你做什麼,它都不會將它從緩存中刪除。所以,我只是移動了查詢並創建了@ NamedQuery註釋mytable實體類,並且調用NamedQuery而不是直接執行SQL。所以,我在「拆解()方法的代碼結束了:

em.CreateNamedQuery("emptyMyTableQuery").executeUpdate(); 

而且@NamedQuery:

@NamedQuery(name="emptyMyTableQuery", query="delete from mytable") 

現在,它完美的作品。老實說,即使在以前版本的EclipseLink中,這個不會出現,我不得不說,這個新版本2.5在幾個方面有幾個增強和改進,並且也修復了很少的錯誤。那麼,希望這有助於有人發現相同的問題。

1

App2是否提交交易?

IntegrityConstraintViolation是從數據庫中拋出的,因此它意味着舊行仍然存在於數據庫中。

打開最好的日誌幷包含兩個應用程序的日誌和完整的異常堆棧跟蹤。

一般而言,轉生對象通常不是一個好主意。最好用新的ID創建一個新對象,或者至少分離/複製到舊對象。

如果另一個應用程序正在訪問同一個數據庫,你可以考慮禁用緩存,

http://wiki.eclipse.org/EclipseLink/FAQ/How_to_disable_the_shared_cache%3F

否則,如果你只是想刷新緩存爲這一個對象,第一次調用find()方法,以確保該對象被管理,然後調用refresh()將其從共享緩存中移除。 (然後你需要分離()它,或清除()你的EntityManager或創建一個新的)。