我们如何使用Hibernate的锁(悲观锁)

来源:互联网 发布:文艺气息的网名知乎 编辑:程序博客网 时间:2024/05/26 20:23
如果想了解乐观锁:http://blog.csdn.net/hushanfeng110/article/details/50174787
-------------------------------------------------------------------------------------------------------------
问题描述:如何在查询的时候对表数据进行锁定,意思就是我要对它进行操作了,其他人谁都不许动。
问题解决方案:使用锁!
关键代码:
      @Override
      public int delParcelByParcelId( long parcelId) {
            int result = 0;
           Session session = getSession( em);
            try {
                 session.getTransaction().begin();
                 // 查询这条数据,并加上锁
                String sql2 = "From Parcel AS p WHERE p.parcelId=:parcelId and p.status=:status";
                List<Parcel> list = session.createQuery( sql2)
                           .setLockMode( "p", LockMode.UPGRADE)//加锁
                           .setParameter( "parcelId"parcelId)
                           .setParameter( "status", 0).list();
                 if ( list.size() > 0) {
                      // 如果存在,表示状态没有被改变 ,可以删除,返回影响行数1,表示删除成功
                     String sql = "UPDATE Parcel AS p set p.status=:status WHERE p.parcelId=:parcelId";
                     Query query = session.createQuery( sql)
                                .setParameter( "status", -1)
                                .setParameter( "parcelId"parcelId);
                      result = query.executeUpdate();
                      session.getTransaction().commit();
                } else {
                      // 如果不存在,说明已经被入库,不能删除,返回-1,表示删除失败
                      session.getTransaction().commit();
                      result = -1;
                }
           } catch (Exception e) {
                 e.printStackTrace();
                 session.getTransaction().rollback();
                 result = 0;
           } finally {
                 if ( session != null) {
                      session.close();
                }
           }
            return result;
     }

备注:当然这是查询的时候的锁表的一种情况,hibernate的insert和update某条记录的时候,会有自带的锁锁定这条数据,所以这个不用担心并行问题。
小诀窍:如果想测试这条数据是否被锁住,可以在提交事务,执行update,加个while(true)死循环(提交事务之前),最好打印点东西,走起的时候,可以看到控制台一直在打印,这个时候你update的这条数据正在被这个session操作,并且被锁定。不信,可以自己在数据库里面另开session执行update这条数据,会卡住一直处于等待中,关掉wildfly,释放资源,这条命令才会执行成功。

个人总结:以上的方法都是使用oracle的自带的锁的机制,叫hibernate的悲观所。还有一种乐观锁,在hibernate的配置文件里面给对应的实体类配置一个version字段,每次执行操作这个字段会自增1,然后通过比较这个字段的,来判断操作是否为最新的操作,这种方法比较好,不占用数据库资源。这个一般用在spring+hibernate里面,使用spring托管hinernate的时候配置。这里我们用不到,就不详细说了。
0 0
原创粉丝点击