Ans*_*shu 2 java spring jpa transactions
我已经搜索了stackoverflow中的帖子,我希望这不是重复.
我第一次尝试使用乐观锁定,我能够使用Spring管理的LockModeType,但无法自己定义LockMode
以下是代码示例:
我正在使用以下方法注入持久化上下文:
@PersistenceContext
private EntityManager entityManager;
Run Code Online (Sandbox Code Playgroud)
第一种方法:使用注释交易
@Transactional
public void updateUserProfile(UserProfile userProfile) {
entityManager.lock(userProfile, LockModeType.OPTIMISTIC); // 1*
entityManager.merge(userProfile);
}
Run Code Online (Sandbox Code Playgroud)
例外1: java.lang.IllegalArgumentException: entity not in the persistence context
第二种方法:管理交易
public void updateUserProfile(UserProfile userProfile) {
entityManager.getTransaction().begin(); // 2*
entityManager.lock(userProfile, LockModeType.OPTIMISTIC);
entityManager.merge(userProfile);
entityManager.getTransaction().commit();
}
Run Code Online (Sandbox Code Playgroud)
2的例外情况: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead
第三种方法:由于我使用共享的entityManager获得了异常,我还尝试从entityManagerFactory创建EntityManager.
@Transactional
public void updateUserProfile(UserProfile userProfile) {
EntityManager em = entityManager.getEntityManagerFactory().createEntityManager();
em.getTransaction().begin();
em.lock(userProfile, LockModeType.OPTIMISTIC); // 3*
em.merge(userProfile);
em.getTransaction().commit();
}
Run Code Online (Sandbox Code Playgroud)
3点的例外情况: entity not in the persistence context
在我的应用程序上下文中,我org.springframework.orm.jpa.JpaTransactionManager用于定义transactionManager和org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean定义entityManagerFactory
提前致谢!
锁定JPA实体的条件:
你似乎违反了(2) - 试图锁定分离的实体.
你可以先合并().
重点:
如果修改实体并运行事务,并且实体中有版本属性,标记为@Version,则会以实体的粒度自动执行乐观锁定.版本属性已更新,如果数据库中尚未更改,则写入成功.这是常见的简单锁定情况,其中对单个实体的所有写入都被序列化以避免损坏.如果可以独立处理每个实体/记录,则无需设置任何LockMode,因为这是默认行为.仔细看看这个选项 - 我怀疑这符合您的简单要求.
如果你有更复杂的处理,需要进行读取或跨多个逻辑相关的实体实例中写道,作为一个始终如一的连贯原子操作,以阻止/隔离期间所有其他写 - 那么你需要设置自己的锁定模式,因为自动化的单个实体锁不起作用.您需要仔细设计以连贯方式读取或写入的实体集,并手动设计和实现您自己的手动锁定解决方案 - 可能选择关系层次结构中的最顶层实体来记录所有的"全局"锁定相关的'子'实体(利用其@Version属性).
任何手动锁定解决方案都需要所有DB写入逻辑来兑现锁定.这意味着在同一实体上运行的其他事务必须了解您的锁定设计,事实上,必须在写入之前尝试取出锁定.锁定不会导致阻塞和序列化的各种写入实际上根本没有锁定.
对于乐观锁定,取出锁定的确切时间是灵活的.在发生提交和刷新操作之前,不会检查锁并将其写入DB.所以你可以在从tx开始到提交的任何时候取出锁.对于悲观锁定,情况恰恰相反 - 您必须保护代码的关键区域,就像您的生活依赖于它一样.通常悲观的lockMode应该被设置为启动事务的em.find()或em.query的一部分 - 或者如果因为托管对象已经在内存中而不可能这样做,那么你应该做一个em.flush()和em.refresh(PESSIMISTIC_WRITE)
= :-)
| 归档时间: |
|
| 查看次数: |
7496 次 |
| 最近记录: |