OpenJPA 锁机制

锁是处理数据库事务并发的一种技术,当两个或更多数据库事务并发地访问相同数据时,锁可以保证同一时间只有一个事务可以修改数据。 

锁的方法通常有两种:乐观锁悲观锁

乐观锁认为多个并发事务之间很少出现冲突,也就是说不会经常出现同一时间读取或修改相同数据,在乐观锁中,其目标是让并发事务自由地同时得到处理,而不是发现或预防冲突。两个事务在同一时刻可以访问相同的数据,但为了预防冲突,需要对数据执行一次检查,检查自上次读取数据以来发生的任何变化。 

悲观锁认为事务会经常发生冲突,在悲观锁中,读取数据的事务会锁定数据,在前面的事务提交之前,其它事务都不能修改数据。 

JPA 2.0 增加了 6 种新的锁模式,其中两个是乐观锁。JPA 2.0 也允许悲观锁,并增加了 3 种悲观锁,第 6 种锁模式是无锁。 

下面是新增的两个乐观锁模式: 

  • OPTIMISTIC:它和READ锁模式相同,JPA 2.0仍然支持READ锁模式,但明确指出在新应用程序中推荐使用OPTIMISTIC。 

  • OPTIMISTIC_FORCE_INCREMENT:它和WRITE锁模式相同,JPA 2.0仍然支持WRITE锁模式,但明确指出在新应用程序中推荐使用OPTIMISTIC_FORCE_INCREMENT。 

下面是新增的三个悲观锁模式:

  • PESSIMISTIC_READ:只要事务读实体,实体管理器就锁定实体,直到事务完成锁才会解开,当你想使用重复读语义查询数据时使用这种锁模式,换句话说就是,当你想确保数据在连续读期间不被修改,这种锁模式不会阻碍其它事务读取数据。 

  • PESSIMISTIC_WRITE:select ...for update只要事务更新实体,实体管理器就会锁定实体,这种锁模式强制尝试修改实体数据的事务串行化,当多个并发更新事务出现更新失败几率较高时使用这种锁模式。

  • PESSIMISTIC_FORCE_INCREMENT:当事务读实体时,实体管理器就锁定实体,当事务结束时会增加实体的版本属性,即使实体没有修改。 

你也可以指定新的锁模式 NONE,在这种情况下表示没有锁发生。 

JPA 2.0 也提供了多种方法为实体指定锁模式,你可以使用 EntityManager 的 lock() 和 find() 方法指定锁模式。此外,EntityManager.refresh() 方法可以恢复实体实例的状态。

示例代码

下面实例通过 EntityManager 的 lock() 方法指定 User 对象的锁级别为 LockModeType.OPTIMISTIC。代码如下:

EntityManagerFactory factory = Persistence.createEntityManagerFactory(
        PERSISTENCE_NAME, System.getProperties());
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();

User user = em.find(User.class, 1);
// 手动指定锁级别
em.lock(user, LockModeType.OPTIMISTIC);
// 修改数据
user.setName("update name");
em.merge(user);

em.getTransaction().commit();
factory.close();
System.out.println("finished.");
说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号