2011-07-07 140 views
6

我會盡力描述JPA的事務隔離級別我的問題。事務隔離級別

數據庫結構:

  • Table1 - >與PK定義爲日期( 'DDMMYYYY')
  • Table2 - >與FK到Table 1

JPA(隔離級別:: read_commited) - code:

Query query = em.createQuery("from Table1 trd where trd.id = :d"); 
    query.setParameter("d", date); 

    Table1 t = null; 
    try{ 
     t = (Table1) query.getSingleResult(); 
    }catch(javax.persistence.NoResultException e){ 
     t = null; 
    } 

    if(t==null){ 
     t=new Table1 (date); 
     em.persist(trd); 
    } 

    for(Table2 q:tables2){ 
     q.setTable1(t); 
     em.merge(q); 
    } 

So procedu重新檢查記錄是否存在於數據庫中,如果沒有創建新記錄。如果系統基於一個線程,方法是完全相同的。否則,有可能發生的情況是這樣的:

  • 主題1:檢查實體代表按日期數據庫中存在
  • 線程2:做同樣的

他們都認爲這樣的記錄有不存在,所以添加一個新的。一切正常,直到提交交易的時刻。沒有任何異常第一個將被COMMITED,購買與主鍵複製相關的第二個上升例外。

是任何可能保留這樣的情況下,只是將隔離級別設置爲SERIALIZABLE

回答

3

是的,在一般的隔離級別= SERIALIZABLE應該解決您的問題。改變隔離級別,以最嚴格的選項時,請不要小看副作用。它可能會影響數據庫利用率以及請求吞吐量。也許你可以在創建T1之後明確提交你的TRX,然後打開另一個TRX: EntityManager.getTransaction()。commit()

你仍然需要捕獲重複密鑰異常。

1

這是在高度併發環境中解決數據庫最困難的問題之一。最後,你唯一真正的解決辦法是捕捉異常,並用它妥善處理。

根據您提供的代碼很難說出可能的結果。如果這是一個web應用程序,那麼很可能您希望捕獲重複的鍵例外情況並向最終用戶顯示一些有用的消息。如「這個記錄已經創建」,或者沿着這些線。