2010-02-07 36 views
6

我是JPA的新手,如果不清楚,請原諒我。如何處理javax.persistence.OptimisticLockException?

基本上我想通過使用樂觀鎖定來防止併發修改。 我已將@Version屬性添加到我的實體類中。

我需要知道處理OptimisticLockException的這個算法是否合理。 我將使用Execute Around Idiom像這樣:

interface UpdateUnitOfWork 
{ 
    doUpdate(User user); /* may throw javax.persistence.PersistenceException */ 
} 

public boolean exec(EntityManager em, String userid, UpdateUnitOfWork work) 
{ 
    User u = em.find(User, userid); 
    if(u == null) 
     return; 

    try 
    { 
     work.doUpdate(u); 
     return true; 
    } 
    catch(OptimisticLockException ole) 
    { 
     return false; 
    } 
} 

public static void main(..) throws Exception 
{ 
    EntityManagerFactory emf = ...; 
    EntityManager em = null; 

    try 
    { 
     em = emf.createEntityManager(); 

     UpdateUnitOfWork uow = new UpdateUnitOfWork() { 
      public doUpdate(User user) 
      { 
       user.setAge(34); 
      } 
     }; 

     boolean success = exec(em, "petit", uow); 
     if(success) 
      return; 

     // retry 2nd time 
     success = exec(em, "petit", uow); 
     if(success) 
      return; 

     // retry 3rd time 
     success = exec(em, "petit", uow); 
     if(success) 
      return; 
    } 
    finally 
    { 
     em.close(); 
    } 
} 

我已經是你如何決定的問題何時停止重試?

回答

9

我的問題是你如何決定何時停止重試?

在我看來,在同一時間修改同一個對象是一種特殊情況時,應該使用樂觀鎖定。

現在,如果出現這種情況,並且過程是手動的,我會提醒用戶修改無法保存並要求他再次保存其更改。

如果這個過程是自動化的,那麼實現一個自動重試機制是有意義的,但根據處理時間的不同,我不會重試超過3或5次的事情(我會使用遞歸調用來實現這個)。如果一個自動化進程在併發訪問問題上連續失敗5次,那麼它很可能與另一個自動化進程競爭,並且他們不是在獨立的數據塊上工作(這不利於並行化),或者策略不是正確的那一個。在這兩種情況下,重試都不是正確的解決方案。