EJB - 使用EntityManager - 可以查找实体导致OptimisticLockException

时间:2013-01-16 16:08:16

标签: jpa transactions ejb entitymanager optimistic-locking

不幸的是,我的代码中出现了一个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()中更新任何东西?

1 个答案:

答案 0 :(得分:1)

来自this博客

  

JPA乐观锁定允许任何人读取和更新实体,但是在提交时进行版本检查,如果在读取实体后数据库中的版本已更新,则抛出异常

因此无需进行更新即可获得OptimisticLockingException。当你阅读它时,假设myEntity.getVersion()== 1。如果在提交时(即当您的test()方法结束时),版本列中的实际值为!= 1,则会出现OptimisticLockingException。

这意味着有人更新了实体(在READ和事务COMMIT之间的平均时间),因此您刚刚读取的值在提交时不再有效。