Hibernate锁

悲观锁
从加载对象就开始锁定。修改过程中一直是锁。直到commit()提交后再解锁。

session.load(Info.class,"p003",LockOptions.UPGRADE);

实例:

public class TestPessimisticLock extends TestCase {
    @Test
    public void testLock1(){
        Session session = null;
        try {
            session = HibernateUtil.getSession();//开始锁定,下面的testLock2不能执行
            session.beginTransaction();
            
            Info data = session.load(Info.class, "p003", LockOptions.UPGRADE);
            data.setName("1111111");
            
            session.getTransaction().commit();//执行以后才解锁,这时testLock2才可以执行
        }  
        catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }
        finally{
            HibernateUtil.closeSession();
        }
    } 
    @Test
    public void testLock2(){
        Session session = null;
        try {
            session = HibernateUtil.getSession();
            session.beginTransaction();
            
            Info data = session.load(Info.class, "p003", LockOptions.UPGRADE);
            data.setName("2222222");
            
            session.getTransaction().commit();
        }  
        catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }
        finally{
            HibernateUtil.closeSession();
        }
    } 
}

乐观锁
实际不算锁,只是多线程控制。在提交时间进行冲突检测。把里面的内容与刚开始读取的内容对照一下。有问题就抛异常。

1.在数据库表中加一个字段version

2.在实体类中加一个属性version

public class Info implements java.io.Serializable {

    private String code;
    private Nation nation;
    private String name;
    private Boolean sex;
    private Date birthday;
    private Set families = new HashSet(0);
    private Set works = new HashSet(0);
    private int version;//添加一个属性version,并生成getter和setter

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

3.在映谢文件中配置<version name="version"> 位置 放在<id></id>下面

<hibernate-mapping>
    <class name="com.itnba.maya.model.Info" table="info" catalog="mydb" optimistic-lock="version">
        <cache usage="read-write"/>
        <id name="code" type="string">
            <column name="Code" length="50" />
            <generator class="assigned" />
        </id>
        
        <!-- 配置version,位置放在<id></id>下面 -->
        <version name="version"></version>
        
        <many-to-one name="nation" class="com.itnba.maya.model.Nation" fetch="select">
            <column name="Nation" length="50" />
        </many-to-one>
        <property name="name" type="string">
            <column name="Name" length="50" />
        </property>
        ....
 </class>
</hibernate-mapping>

其余代码不做改变。 

实例:

public class TestOptimisticLock extends TestCase{
    @Test
    public void testLock2(){
        Session session = null;
        try {
            session = HibernateUtil.getSession();
            session.beginTransaction();
            
            Info data = session.load(Info.class, "p002");
            data.setName("2222222");
            
            session.getTransaction().commit();//在此时进行冲突检测,version的值与刚开始读取的version值比较。值不同就就抛异常,意为无法操作。
        }  
        catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }
        finally{
            HibernateUtil.closeSession();
        }
    }
    @Test
    public void testLock1(){
        Session session = null;
        try {
            session = HibernateUtil.getSession();
            session.beginTransaction();
            
            Info data = session.load(Info.class, "p002");
            data.setName("1111111");
            
            session.getTransaction().commit();
        }  
        catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }
        finally{
            HibernateUtil.closeSession();
        }
    }
}

 

假如没有使用hibernate,那么这样来处理并发冲突 

Info oldInfo = ...

Info newInfo =...

//where前面的内容用newInfo的属性,where后面的内容用oldInfo的属性
update info set name=?,sex=?,nation=?,birthday=? where code=? and name=? and sex=? and nation=? and birthday=?


executeUpdate(); //返回值为int,如果出现冲突,提示-更新的行数0----表示有并发冲突
原文地址:https://www.cnblogs.com/jonsnow/p/6534962.html