2011-06-01 87 views
1

我有以下設置: 春天 - > JPA - >休眠 - > PostgreSQL的春/ JPA /休眠/ PostgreSQL的拋出EntityNotFoundException在嵌套事務

我已經創建了提供了一些 「@Transactional」 服務層插入數據的方法。數據在具體情況下是必須連接到類別實體(識別關係)和一些圖片實體(非識別關係)的個人實體。

由於我必須提供導入程序,因此我創建了一個方法(也稱爲@Transactional)來導入csv文件。此方法首先嚐試插入類別(這可以很好地使用從服務層調用的DAO中使用的em.persist())。然後,我添加一個新的人員,該人員與之前添加的類別相連(該類別已被加載,就像它已經存在於數據庫 - > HQL查詢中一樣),該類別也在正在運行的事務中持續存在。人員實體也使用em.persist()來獲取事務中的持久化。

現在我創建圖片實體並將它們連接到人物實體。連接它們之後,我也保存這個人,但是因爲它已經在事務中保留了,我使用em.merge()。在這裏我得到一個「EntityNotFoundException()」作爲休眠(或jpa)無法從第一步加載類別(它有一個正確的ID,但它似乎看不到交易)...

全部三種方法insertCategory(),insertPerson()和addPicture()也被聲明爲@Transaction,因爲它們在正常用例中是分開使用的。也許這個問題與嵌套事務有關,但它更像是與em.merge()相關,因爲em.persist()運行良好。

em是從Spring中注入的EntityManager。

任何想法發生了什麼問題?

問候奔

回答

1

如果您正在使用代理(事務處理的春天默認值)時方法正在內一類叫做@Transactional註釋被忽略。以下將不起作用:

@Transactional 
public void doStuff() { 
    this.doSomeOtherStuff(); 
} 

@Transactional(propagation=Propagation.REQUIRES_NEW) 
public void doSomeOtherStuff() { 
    // do some more db work here. 
} 

如果你確實這樣做,你有兩個選擇:

  1. 用AspectJ,而不是代理。這需要一點學習曲線。
  2. 將需要交易的方法移到另一個類中。

您可以在Spring文檔here中閱讀更多關於此的信息。

在代理模式下(默認),只攔截通過代理進入的外部方法調用。這意味着即使被調用的方法標記爲@Transactional,實際上,自調用目標對象內的方法調用目標對象的另一個方法也不會導致實際的事務處理。