Hibernate学习---第十二节:Hibernate之锁机制&乐观锁实现

一、悲观锁java

它指的是对数据被外界修改保持保守态度,因些,在整个数据处理过程当中,将数据牌锁定状态。悲观锁的实现,每每依靠数据库提供的锁机制(也只有数据库层的锁机制才能保证数据访问的排他性,不然,即便在本系统中实现了加锁机制,也没法保证外部系统不会修改数据)。 数据库

一个典型的悲观锁调用示例: app

select * from account where name = "12345" for update ide

经过for update子句,这条SQL锁定了account表中全部符合检索条件的记录。本次事务提交以前(事务提交时会释放事务过程当中的锁),外界没法修改这些记录。 函数

二、乐观锁性能

相对悲观锁而言,乐观锁机制采起了更加宽松的加锁机制。悲观锁大多数状况下依靠数据库的锁机制,以操做最大程度的独占性。但随着而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销每每没法承受。 测试

乐观锁,大可能是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增长一个版本标识,在基于库表的版本解决方案中,通常是经过为数据库表增长version字段来实现。 this

读取出数据时,将此版本号一同读出,之生更新时,对此版本号加1.此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,若是提交的数据版本号大于数据库表当前版本号,则予以更新,不然认为是过时数据。 spa

例如,两我的同时在同一个账号取钱,帐号有100,A取50,B取20,A先提交,B的余额即为80,这时就不一样步了,A提交后版本已经变了2了,而B看到的仍是1的版本,此时B的提交必须被驳回。 .net

须要注意的是,乐观锁机制每每基于系统中的数据存储逻辑,所以也具有必定的局限性。若有些例子,因为乐观锁机制是在咱们的系统中实现,来自外部系统的用户余额更新操做不受咱们系统控制,所以可能会形成非法数据被更新到数据库中。

在系统设计阶段,咱们应该充分考虑到某些状况出现的可能性,并进行相应调整(如将乐观锁策略在数据库存储过程当中实现,对外只开放基于此存储过程的数据更新途径,而不是将数据库表直接对外公开)。

Hibernate 在其数据访问引擎中内置了乐观锁实现。若是不用考虑外部系统对数据库的更新操做,利用Hibernate提供的透明化乐观锁实现,将大大提高咱们的生产力。

(1)、实体类

package learn.hibernate.bean;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * 持久化类设计
 * 注意:
 *         持久化类一般建议要有一个持久化标识符(ID)
 *         持久化标识符一般建议使用封装类(例如:Integer  由于基本类型存在默认值)
 *         持久化类一般建议手动添加一个无参构造函数 (由于有些操做是经过放射机制进行的)
 *         属性一般建议提供  getter/setter 方法
 *         持久化类不能使用 final 修饰
 *         持久化类中若是使用了集合类型数据,只能使用集合所对应的接口类型来声明(List/Map/Set)
 *              以下:ArrayList list = new ArrayList();  不行
 *                 List list = new ArrayList(); 可行
 */
public class Person {

    private Integer id;
    private String name;
    private int age;
    private int passwork;
    private Date birthday;
    private Integer version;
    
    public Person() {
        
    }
    
    public Person(String name, int age, int passwork, Date birthday) {
        super();
        this.name = name;
        this.age = age;
        this.passwork = passwork;
        this.birthday = birthday;
    }
    
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", age=" + age
                + ", passwork=" + passwork + ", birthday=" + birthday + "]";
    }
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getPasswork() {
        return passwork;
    }
    public void setPasswork(int passwork) {
        this.passwork = passwork;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Integer getVersion() {
        return version;
    }

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

(2)、持久化映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="learn.hibernate.bean">
    <!-- 
        optimistic-lock="version" 指定持久化类的乐观锁策略
     -->
    <class name="Person" table="t_person" optimistic-lock="version">
        <id name="id" column="person_id">
            <generator class="native"/>
        </id>
        <!-- 配置 锁字段和对应的属性关联,以及字段类型 -->
        <version name="version" column="t_version" type="integer"/>
        <property name="name" column="t_name"/>
        <property name="age"/>    
        <property name="passwork"/>
        <property name="birthday"/>
    </class>
</hibernate-mapping>

(3)、测试类

/**
 * hibernate 在获取数据的时候返回一个锁状态
 * 在提交数据的时候会自动的将锁状态进行改变
 */
@Test
public void testUpdate(){
    Person p1 = (Person)s1.get(Person.class, 1);
    Person p2 = (Person)s2.get(Person.class, 1);
    
    System.out.println("----------1---start-----------");
    tx = s1.beginTransaction();
    p1.setName("p1");
    s1.update(p1);
    tx.commit();
    System.out.println("----------1---end-----------");
    
    System.out.println("----------2---start-----------");
    tx = s2.beginTransaction();
    p2.setName("p2");
    s2.update(p2);
    tx.commit();
    System.out.println("----------2---end-----------");
}

能够查看:http://blog.csdn.net/shen516/article/details/8599068

相关文章
相关标签/搜索