`

hibernate 乐观所使用

阅读更多

 

 

 

 

通过在表中及POJO中增加一个version字段来表示记录的版本,来达到多用户同时更改一条数据的冲突

数据库脚本:

create table studentVersion (id varchar(32),name varchar(32),ver int);

1 实体类

 

 
package Version;

public class Student {
  private String id;
  private String name;
  private int version;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getVersion() {
		return version;
	}
	public void setVersion(int version) {
		this.version = version;
	}
}

2 实体配置文件  Student.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="Version.Student" table="studentVersion" optimistic-lock="version"  >
    <id name="id" unsaved-value="null">
      <generator class="uuid.hex"></generator>
    </id>
    <!--version标签必须跟在id标签后面-->
    <version name="version" column="ver" type="int"></version>
    <property name="name" type="string" column="name"></property>  
</class>

</hibernate-mapping>

 

3  hbernate.cfg.xml 主配置文件

 

  

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>
<session-factory>
    <property name="connection.username">root</property>
    <property name="connection.url">
        jdbc:mysql://localhost:3306/schoolproject?characterEncoding=gb2312&amp;useUnicode=true
    </property>
    <property name="dialect">
        org.hibernate.dialect.MySQLDialect
    </property>
    <property name="myeclipse.connection.profile">mysql</property>
    <property name="connection.password">1234</property>
    <property name="connection.driver_class">
        com.mysql.jdbc.Driver
    </property>
    <property name="hibernate.show_sql">true</property>
    <property name="current_session_context_class">thread</property>
    <property name="jdbc.batch_size">15</property>
    <mapping resource="Version/Student.hbm.xml" />

</session-factory>

</hibernate-configuration>

   

4 hibernage 的测试代码

import java.io.File;
import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class Test {
    public static void main(String[] args) {

        String filePath=System.getProperty("user.dir")+File.separator+"src/Version"+File.separator+"hibernate.cfg.xml";
        File file=new File(filePath);
        System.out.println(filePath);
        SessionFactory sessionFactory=new Configuration().configure(file).buildSessionFactory();
        Session session=sessionFactory.openSession();
        Transaction t=session.beginTransaction();
        
        Student stu=new Student();
        stu.setName("tom11");
        session.save(stu);
        t.commit();
        
        /*
         * 模拟多个session操作student数据表
         */
        
        Session session1=sessionFactory.openSession();
        Session session2=sessionFactory.openSession();
        Student stu1=(Student)session1.createQuery("from Student s where s.name='tom11'").uniqueResult();
        Student stu2=(Student)session2.createQuery("from Student s where s.name='tom11'").uniqueResult();
        
        //这时候,两个版本号是相同的
        System.out.println("v1="+stu1.getVersion()+"--v2="+stu2.getVersion());
        
        Transaction tx1=session1.beginTransaction();
        stu1.setName("session1");
        tx1.commit();
        //这时候,两个版本号是不同的,其中一个的版本号递增了
        System.out.println("v1="+stu1.getVersion()+"--v2="+stu2.getVersion());
        
        Transaction tx2=session2.beginTransaction();
        stu2.setName("session2");
        tx2.commit();     
        
    }
}

 

运行结果:

Hibernate: insert into studentVersion (ver, name, id) values (?, ?, ?)

Hibernate: select student0_.id as id0_, student0_.ver as ver0_, student0_.name as name0_ from studentVersion student0_ where student0_.name='tom11'

Hibernate: select student0_.id as id0_, student0_.ver as ver0_, student0_.name as name0_ from studentVersion student0_ where student0_.name='tom11'

v1=0--v2=0

Hibernate: update studentVersion set ver=?, name=? where id=? and ver=?

v1=1--v2=0

Hibernate: update studentVersion set ver=?, name=? where id=? and ver=?

Exception in thread "main" org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Version.Student#4028818316cd6b460116cd6b50830001]

 

可以看到,第二个“用户”session2修改数据时候,记录的版本号已经被session1更新过了,所以抛出了红色的异常,我们可以在实际应用中处理这个异常,例如在处理中重新读取数据库中的数据,同时将目前的数据与数据库中的数据展示出来,让使用者有机会比较一下,或者设计程序自动读取新的数据

 

注意:如果手工设置stu.setVersion()自行更新版本以跳过检查,则这种乐观锁就会失效,应对方法可以将Student.java的setVersion设置成private

 

 

 

 

 

 

分享到:
评论

相关推荐

    Hibernate乐观锁和悲观锁分析

    Hibernate乐观锁和悲观锁分析,针对在使用HIBERNATE时怎么配置乐观锁进行了详细的范例讲解

    hibernate乐观锁和悲观锁学习

    其中通过 version 实现的乐观锁机制是 Hibernate 官方推荐的乐观锁实现,同时也是 Hibernate 中,目前唯一在数据对象脱离 Session 发生修改的情况下依然有效的锁机制。因此,一般情况下,我们都选择 version 方式...

    Hibernate乐观锁

    学习hibernate的必备知识,当你学习hibernate时,就会对锁的概念有一定的了解了.

    Hibernate的乐观锁与悲观锁

    Hibernate的乐观锁与悲观锁的文档,帮助学习Hibernate的乐观锁与悲观锁,让你们学得更轻松。

    Hibernate version 乐观锁 (xml方式)

    NULL 博文链接:https://tgwall163.iteye.com/blog/1291892

    hibernate乐观锁

    乐观锁 求助编辑百科名片相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库 性能的大量开销,特别是对长事务而...

    hibernate的乐观锁和悲观锁

    hibernate的乐观锁和悲观锁,两种锁搞定一切

    Hibernate悲观锁和乐观锁的实现

    NULL 博文链接:https://12345678.iteye.com/blog/721836

    Hibernate 乐观和悲观锁

    NULL 博文链接:https://jordanyangwei.iteye.com/blog/313756

    Hibernate锁机制_悲观锁和乐观锁

    Hibernate锁机制_悲观锁和乐观锁

    Hibernate悲观锁与乐观锁

    很好的描述Hibernate的悲观锁和乐观锁,

    Hibernate悲观锁与乐观锁案例

    Hibernate高级特性,悲观锁与乐观锁的应用和区别,及两者之间的区别。

    Hibernate+中文文档

    11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...

    Hibernate Annotations 中文文档

    乐观锁定版本控制 2.2.2. 映射简单属性 2.2.2.1. 声明基本的属性映射 2.2.2.2. 声明列属性 2.2.2.3. 嵌入式对象(又名组件) 2.2.2.4. 无注解之属性的默认值 2.2.. 映射主键属性 2.2.4. 映射继承关系 2.2.4.1. ...

    hibernate3.2中文文档(chm格式)

    11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...

    HibernateAPI中文版.chm

    11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 扩展周期的session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...

    最全Hibernate 参考文档

    11.3. 乐观并发控制(Optimistic concurrency control) 11.3.1. 应用程序级别的版本检查(Application version checking) 11.3.2. 长生命周期session和自动版本化 11.3.3. 脱管对象(deatched object)和自动版本化 ...

    Hibernate实战(第2版 中文高清版)

     2.2.2 使用Hibernate EntityManager   2.2.3 引入EJB组件   2.2.4 切换到Hibernate接口   2.3 反向工程遗留数据库   2.3.1 创建数据库配置   2.3.2 定制反向工程   2.3.3 生成Java源代码   2.4 与...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     21.5 利用Hibernate的版本控制来实现乐观锁  21.5.1 使用元素  21.5.2 使用元素  21.5.3 对游离对象进行版本检查  21.5.4 强制更新版本  21.6 实现乐观锁的其他方法  21.7 小结  21.8 思考题 第22章 管理...

    Hibernate实现悲观锁和乐观锁代码介绍

    主要介绍了Hibernate实现悲观锁和乐观锁的有关内容,涉及hibernate的隔离机制,以及实现悲观锁和乐观锁的代码实现,需要的朋友可以了解下。

Global site tag (gtag.js) - Google Analytics