2017-05-05 79 views
10

我有一個休息應用程序,其中一個資源可以更新。下面是兩種方法負責實現這個任務:使用JPA合併時的OptimisticLockException()

  1. updateWithRelatedEntities(字符串,商店):接收ID和被反序列化PUT請求的實體建造新的對象存儲,設置版本(用於樂觀鎖)在新對象上並在事務中調用更新。

    public Store updateWithRelatedEntities(String id, Store newStore) { 
        Store existingStore = this.get(id); 
    
        newStore.setVersion(existingStore.getVersion()); 
    
        em.getTransaction().begin(); 
        newStore = super.update(id, newStore); 
        em.getTransaction().commit(); 
    
        return newStore; 
    } 
    
  2. 更新(字符串,T):用於使一個更新的通用方法。檢查ID匹配並執行合併操作。

    public T update(String id, T newObj) { 
        if (newObj == null) { 
        throw new EmptyPayloadException(type.getSimpleName()); 
        } 
    
    
        Type superclass = getClass().getGenericSuperclass(); 
    
        if (superclass instanceof Class) { 
         superclass = ((Class) superclass).getGenericSuperclass(); 
        } 
    
        Class<T> type = (Class<T>) (((ParameterizedType) superclass).getActualTypeArguments()[0]); 
    
        T obj = em.find(type, id); 
    
        if (!newObj.getId().equals(obj.getId())) { 
         throw new IdMismatchException(id, newObj.getId()); 
        } 
    
        return em.merge(newObj); 
    } 
    

的問題是,這一呼籲:T obj = em.find(type, id);觸發在數據庫中存儲對象的更新,這意味着我們觸發merge時(因爲版本不同,現在)得到OptimisticLockException。

這是怎麼發生的?什麼纔是實現這一目標的正確方法?

我不想複製newStore的屬性到existingStore並使用existingStore進行合併 - 我認爲這會解決樂觀鎖定問題。

此代碼未在應用程序服務器上運行,我沒有使用JTA。

編輯: 如果我調用Update之前分離existingStore,T obj = em.find(type, id);並不那麼這解決了問題,引發存儲對象的更新。但問題仍然存在 - 爲什麼它在實體不分離時觸發它?

+0

你明白樂觀鎖定的概念嗎? – Kayaman

+0

是的,我理解這個概念以及爲什麼我得到這個錯誤。我不明白的是爲什麼JPA在調用get(id)時更新版本,當調用merge時會導致OptimistiLockException。 –

+0

get(id)是什麼樣的? – Kayaman

回答

1

我無法從您添加的代碼中看到您的實體,但我相信您在版本字段上缺少樂觀鎖定的某個關鍵點 - >@Version註釋。 如果你的實體上有這個字段,那麼容器應該能夠做到沒有問題的合併過程。請看看 Optimistic Locking也不錯的文章don't break optimistic locking

+0

我正在使用'@ Version'字段,問題是我正在用一個新對象(由反序列化構造)​​進行更新,因此我必須手動設置'@ Version'字段。 –

+0

爲什麼不只是反序列化對象,並把它作爲id,做一個'em.find',然後你可以更新適當的實體。你現在正在做的是有點hacky .. – galovics

+0

這將是一個解決方案,但我不喜歡它,因爲我知道哪些領域,我不想複製,而不是其他方式。因此,如果將來添加一個字段給實體,我將不得不記住我必須將該字段添加到代碼庫的另一部分。 –