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语句对数据不加锁

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

3. 如果改成.setLockMode(LockModeType.PESSIMISTIC_WRITE), 才能保证数据安全, 避免脏读问题


猜你喜欢

转载自blog.csdn.net/asdfsadfasdfsa/article/details/80013777