hibernate查询使用默认锁,加读锁,加写锁测试

UserDao

@Repository
public class UserDao {

    @PersistenceContext
    private EntityManager entityManager;

    public User get(Long id) {
        String hql = "select u from User u where id = :id";
        return entityManager.createQuery(hql, User.class).setParameter("id", id)
                .setLockMode(LockModeType.PESSIMISTIC_READ)
                .getSingleResult();
    }

    public void update(Integer age, Long id) {
        String hql = "update User set age = :age where id = :id";
        entityManager.createQuery(hql).setParameter("age", age).setParameter("id", id).executeUpdate();
    }
}

UserService

 @Service
 @Transactional
public class UserService {

     @Autowired
    private UserDao userDao;

     public void update()  {
         User user = userDao.get(1L);
         try {
             TimeUnit.MILLISECONDS.sleep(50);
         }catch (Exception e){

         }

         userDao.update(user.getAge()+1,1L);
     }

     public class InnerThread implements Runnable{

         @Override
         public void run() {

                 update();


         }
     }
}

Test

 @Test
    public void contextLoads(){
        for(int i =0;i<2;i++){
            new Thread(userService.new InnerThread()).start();
        }

        try {

            TimeUnit.SECONDS.sleep(5);
        }catch (Exception e){

        }

        System.out.println("over");

    }

1. 如果UserDao里的get语句把.setLockMode注释, 则存在第二类丢失更新, 两次update, 实际上只做了一次. 说明默认情况下, select语句对数据不加锁, RR和RC隔离级别的读是一致性非锁定读, 即快照读

2. 如果改成.setLockMode(LockModeType.PESSIMISTIC_READ), 则会产生死锁

3. 如果改成.setLockMode(LockModeType.PESSIMISTIC_WRITE), 才能保证数据安全, 避免第二类丢失更新

4. setLocalMode加锁模式, 使用的是DB底层的悲观锁原理, 此外还可以通过hibernate提供的乐观锁来做数据安全控制


posted @ 2018-04-20 09:17  車輪の唄  阅读(17)  评论(0编辑  收藏  举报  来源