`

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,作为Java领域广泛使用的ORM框架,提供了一种处理并发数据访问冲突的手段,那就是锁机制。主要...

    Hibernate乐观锁

    Hibernate乐观锁是数据库事务控制的一种策略,主要用于处理并发更新数据的情况。在乐观锁的机制下,假设并发用户很少会发生冲突,所以在读取数据时不会进行任何锁定,而在更新数据时才会检查在此期间是否有其他用户...

    hibernate乐观锁和悲观锁学习

    本文主要讨论的是Hibernate框架中两种锁机制的使用:乐观锁和悲观锁。 首先,让我们深入理解悲观锁(Pessimistic Locking)。悲观锁正如其名字所示,假设并发环境中数据会被频繁修改,所以在整个数据处理过程中,它...

    Hibernate悲观锁和乐观锁的实现

    在Hibernate源码中,乐观锁的实现主要依赖于`AbstractEntityPersister`类的`checkOptimisticLocking()`方法,它会比较当前对象的版本信息与数据库中的版本信息,如果不同则抛出`StaleObjectStateException`异常。...

    Hibernate的乐观锁与悲观锁

    ### Hibernate的乐观锁与悲观锁 #### 一、引言 在并发环境下,尤其是在金融、电商等业务场景中,确保数据的一致性和完整性至关重要。**Hibernate**作为一种流行的Java持久层框架,提供了多种机制来处理并发控制...

    Hibernate 乐观和悲观锁

    标题中的“Hibernate 乐观和悲观锁”涉及到的是Java领域中持久化框架Hibernate中的一种数据并发控制策略。在多线程环境下,为了保证数据的一致性和完整性,数据库管理系统提供了多种锁定机制,其中乐观锁和悲观锁是...

    hibernate的乐观锁和悲观锁

    ### Hibernate的乐观锁和悲观锁 #### 一、引言 在软件开发中,尤其是在涉及大量并发操作的应用场景下,确保数据的一致性和完整性是非常重要的。对于基于Java Web的应用而言,Hibernate作为一款流行的ORM框架,提供...

    hibernate乐观锁

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

    Hibernate version 乐观锁 (xml方式)

    在了解了Hibernate乐观锁的XML配置后,我们可以结合源码进一步分析其实现细节。在Hibernate中,乐观锁的处理主要在`org.hibernate.event.internal.DefaultMergeEventListener`和`org.hibernate.event.internal....

    Hibernate5中文用户使用手册

    整体来看,本手册为Hibernate5的使用者提供了详尽的指导,从基础架构开始,到具体的编程实践,再到性能优化和高级特性,覆盖了使用Hibernate进行Java持久化编程所需的所有知识点。对于初学者而言,是学习Hibernate的...

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

    Hibernate 锁机制是指在数据库访问中,为了维护数据的一致性和正确性,所采取的一些机制来防止数据的并发访问和修改。 Hibernate 中有两种锁机制:悲观锁和乐观锁。 一、悲观锁(Pessimistic Locking) 悲观锁是一...

    Hibernate 一对多双向映射及乐观锁使用

    4. **Hibernate乐观锁实现**:在Hibernate中,可以通过在实体类上添加`@Version`注解来启用乐观锁,该注解对应的字段会在数据库中自动生成并维护。在更新时,Hibernate会自动处理版本号的比较和更新。 5. **配置...

    数据库事务、hibernate悲观锁和乐观锁

    在《hibernate_3200_Concurrency_Pessimistic_Lock》这个压缩包中,很可能包含了关于Hibernate框架如何实现悲观锁和乐观锁的详细资料,包括源代码示例、配置方法和使用场景。通过学习这些资料,你可以深入了解这两种...

    Hibernate悲观锁与乐观锁

    例如,以下代码展示了如何在Hibernate中使用悲观锁: ```java Query query = session.createQuery("from User user"); query.setLockMode("user", LockMode.UPGRADE); ``` 这段代码在执行查询前,通过`setLockMode...

    Hibernate悲观锁与乐观锁案例

    总的来说,Hibernate的悲观锁和乐观锁是处理并发问题的重要工具,开发者需要根据实际情况权衡性能和数据一致性,合理选择并使用合适的锁策略。在实际项目中,还可以结合使用其他的并发控制手段,如事务隔离级别、...

    Hibernate面试题专栏 - 最全的Hibernate面试题, Hibernate笔试题, Hibernate问题

    以上只是Hibernate众多知识点的一部分,实际面试中可能涉及更多细节,如级联操作、事务隔离级别、延迟加载机制、乐观锁和悲观锁的区别等。熟悉并理解这些内容对于通过Hibernate相关的面试至关重要。

    Hibernate注解用法总结

    - `@Version`: 用于实现乐观锁机制,通常与版本字段一起使用,每次更新数据时,会检查此字段是否与数据库中的值一致,确保数据一致性。 - `@Column`: 用于将实体的属性映射到数据库表的列,可以自定义列的名称、...

    hibernate中文帮助文档

    这个中文帮助文档详细介绍了如何使用Hibernate的注解来配置实体Bean,实现与数据库的无缝对接。 1. 创建注解项目: 在开始使用Hibernate的注解之前,你需要满足一定的系统需求,包括JDK、Hibernate库以及兼容的...

    Hibernate电子书(全)

    #### Hibernate所需类库 在使用Hibernate之前,需要确保系统中已经安装了JDBC驱动程序,这是为了能够与关系数据库进行通信。对于MySQL用户,需要从MySQL官网下载相应的JDBC驱动。此外,还需要下载Hibernate的最新...

Global site tag (gtag.js) - Google Analytics