2013-01-16 36 views
2

不幸的是,我在我的代碼中得到一個OptimisticLockException,我不知道爲什麼。也許有人可以幫助我解答一般性問題。EJB - 使用一個EntityManager - 可以找到一個實體導致一個OptimisticLockException

以下情形:

@Entity 
public class MyEntity { 
    @Id 
    @GeneratedValue 
    private Integer id; 

    @Version 
    private int version; 

    private String value; 
} 

@Singleton 
@TransactionManagement(TransactionManagementType.CONTAINER) 
public class MyBean { 
    @PersistenceContext 
    private EntityManager em; 

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public void test() { 

     MyEntity myEntity = em.find(MyEntity.class, 1); 

    } 
} 

CMT使用。方法test()需要一個新的事務。

現在我的問題:如果在另一個bean中有另一個線程使用相同的持久化上下文在提交之前更改我的實體,那麼方法test()會拋出一個OptimisticLockException,儘管我只使用find並且不更新我的方法test中的任何東西)?

+0

你是如何獲得EntityManager的?它們通常不是線程安全的 - 大多數容器在啓動事務時將在代理EM後面獲得新的EntityManager,因此您可能需要檢查您的配置。 – Chris

回答

1

this博客

JPA樂觀鎖允許任何人閱讀和更新實體,但是版本檢查是在提交時提出,如果版本在數據庫中更新,因爲實體是拋出一個異常閱讀

因此,不需要進行更新以獲得OptimisticLockingException。當你讀它時,假設myEntity.getVersion()== 1。如果在提交時(即,當您的test()方法結束時),則會出現OptimisticLockingException,版本列中的實際值爲!= 1.

這意味着某人更新了實體(在READ和事務COMMIT),所以剛剛讀取的值在提交時不再有效。

+0

感謝您的回答!我猜對了,但並不確定。 –

+0

博客文章還提到了JPA實體鎖定API的額外鎖定。我試圖找出默認設置。有一些消息說默認是沒有鎖定的。如果我現在選擇「OPTIMISTIC」,使用OPTIMISTIC沒有區別嗎?因爲博客總是說「提交時進行版本檢查」? (我知道,鎖定是隻爲我定義的實體,如果我在find()方法中使用它) –

+0

這可能取決於提供程序,但我不知道任何提供程序將檢查版本字段樂觀鎖定,除非有更新,刪除或插入來執行。查找不應該導致樂觀鎖定異常,除非有刷新的實體更改。 – Chris

相關問題