zoukankan      html  css  js  c++  java
  • hibernate悲观锁和乐观锁 Mr

    ibernate中经常用到当多个人对同一数据同时进行修改的时候,会发生脏数据,造成数据的不一致性,解决办法是可以通过悲观锁和乐观锁来实现。
    悲观锁:在数据有加载的时候就给其进行加锁,直到该锁被释放掉,其他用户才可以进行修改,优点:数据的一致性保持得很好,缺点:不适合多个用户并发访问。当一个锁住的资源不被释放掉的时候,这个资源永远不会被其他用户进行修改,容易造成无限期的等待。
    乐观锁:就是在对数据进行修改的时候,对数据才去版本或者时间戳等方式来比较,数据是否一致性来实现加锁。优点比较好。
    1、在悲观锁中,只要在加载的时候,才去session中的load方法,进行枷锁,session.load(****.class,1,LockMode.UPDATE);

          Hibernate将事务管理委托给底层的JDBC或者JTA,默认是基于JDBC Transaction的。
          Hibernate支持悲观锁(Pessimistic Locking乐观锁(Optimistic Locking
          悲观锁对数据被外界修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制。Hibernate通过使用数据库的for update子句实现了悲观锁机制。Hibernate的加锁模式有:
          1. LockMode.NONE:无锁机制
          2. LockMode.WRITEHibernateInsertUpdate记录的时候会自动获取
          3. LockMode.READHibernate在读取记录的时候会自动获取
          4. LockMode.UPGRADE:利用数据库的for update子句加锁
          5. LockMode.UPGRADE_NOWAITOracle的特定实现,利用Oraclefor update nowait子句实现加锁
    2乐观锁大多是基于数据版本(Version)记录机制实现。Hibernate在其数据访问引擎中内置了乐观锁实现,可以通过class描述符的optimistic-lock属性结合version描述符指定。optimistic-lock属性有如下可选取值:
          1. none:无乐观锁
          2. version:通过版本机制实现乐观锁
          3. dirty:通过检查发生变动过的属性实现乐观锁
          4. all:通过检查所有属性实现乐观锁
    例子:
    1、悲观锁:
    1>POJO
    public class PersimisticLocking {
     private int id;
     
     private String Item;
     
     private int price;
    //省略settergetter方法
    }
    2>POJO类的映射文件

     1<?xml version="1.0"?>
     2<!DOCTYPE hibernate-mapping PUBLIC 
     3    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     4    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     5<hibernate-mapping package="org.apple.hibernate">
     6    <class name="PersimisticLocking" table="t_persimisticLocking">
     7        <id name="id">
     8            <generator class="native"/>
     9        </id>
    10        <property name="item"/>
    11        <property name="price"/>
    12    </class>
    13</hibernate-mapping>

    3>、加载测试方法

     1public void testLoad1()
     2    {
     3        Session session = null;
     4        try {
     5            session = HibernateUtil.getSession();
     6            session.beginTransaction();
     7            OptimisticLocking o = (OptimisticLocking)session.load(OptimisticLocking.class, 1);
     8            System.out.println("o.item="+o.getItem());
     9            System.out.println("o.price="+o.getPrice());
    10            System.out.println("o.version="+o.getVersion());
    11            o.setPrice(o.getPrice()-10);
    12            session.update(o);
    13            session.beginTransaction().commit();
    14        } catch (Exception e) {
    15            // TODO: handle exception
    16            e.printStackTrace();
    17            session.beginTransaction().rollback();
    18        }finally{
    19            HibernateUtil.closeSession(session);
    20        }
    21        
    22    }

    PS:可以设置另外类似的方法,不枷锁,先对上面的测试代码设置断点,点debug一部分,再运行不枷锁的,可以看到,如果上面方法不释放锁的话,下面的数据就会造成无限期的等待。
    2、乐观锁:
    1>在悲观锁的基础上加入private int version;和相关的settergetter方法。
    2>映射文件配置在class标签里面加入optimistic-lock="version",然后在的id标签后面加入<version name="version"/>
    3>测试方法:

     1public void testLoad1()
     2    {
     3        Session session = null;
     4        try {
     5            session = HibernateUtil.getSession();
     6            session.beginTransaction();
     7            OptimisticLocking o = (OptimisticLocking)session.load(OptimisticLocking.class, 1);
     8            System.out.println("o.item="+o.getItem());
     9            System.out.println("o.price="+o.getPrice());
    10            System.out.println("o.version="+o.getVersion());
    11            o.setPrice(o.getPrice()-10);
    12            session.update(o);
    13            session.beginTransaction().commit();
    14        } catch (Exception e) {
    15            // TODO: handle exception
    16            e.printStackTrace();
    17            session.beginTransaction().rollback();
    18        }finally{
    19            HibernateUtil.closeSession(session);
    20        }
    21        
    22    }


    PS:在初始数据的时候,version0,在没更新一次version都会在原来的基础上加1,通过version的版本来实现乐观锁。
    在上面的测试方法里面复制成另外一个方法,对上面的方法进行设置断点,然后单步调试几部,到NO.11行的时候暂停,此时对复制的另外方法运行,然后再运行完上面的方法,就会抛出异常,所以,在实际的项目开发中,可以通过对异常进行出来,这样就会实现并发访问。

    Mr-sniper
    北京市海淀区
    邮箱:rafx_z@hotmail.com
  • 相关阅读:
    连接ESP32失败:等待包头 #226超时
    题王网
    高可用架构模式——CAP
    高性能负载均衡
    单服务器高性能模式
    虚拟支付
    高性能架构设计——数据库篇
    MySQL
    shell 命令: MD5
    HTTPS
  • 原文地址:https://www.cnblogs.com/rafx/p/lock.html
Copyright © 2011-2022 走看看