2013-01-16 16 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

相关问题