`

Hibernate并发控制乐观锁实现-Version

 
阅读更多

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

数据库脚本:

createtablestudentVersion(idvarchar(32),namevarchar(32),verint);

POJO

packageVersion;

publicclassStudent{
privateStringid;
privateStringname;
privateintversion;
publicStringgetId(){
returnid;
}

publicvoidsetId(Stringid){
this.id=id;
}

publicStringgetName(){
returnname;
}

publicvoidsetName(Stringname){
this.name=name;
}

publicintgetVersion(){
returnversion;
}

publicvoidsetVersion(intversion){
this.version=version;
}



}

Student.hbm.xml

<?xmlversion="1.0"encoding="utf-8"?>
<!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--
MappingfileautogeneratedbyMyEclipse-HibernateTools
-->
<hibernate-mapping>
<classname="Version.Student"table="studentVersion">
<idname="id"unsaved-value="null">
<generatorclass="uuid.hex"></generator>
</id>
<!--version标签必须跟在id标签后面-->
<versionname="version"column="ver"type="int"></version>
<propertyname="name"type="string"column="name"></property>
</class>

</hibernate-mapping>

Hibernate.cfg.xml

<?xmlversion='1.0'encoding='UTF-8'?>
<!DOCTYPEhibernate-configurationPUBLIC
"-//Hibernate/HibernateConfigurationDTD3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"
>

<!--GeneratedbyMyEclipseHibernateTools.-->
<hibernate-configuration>

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




</session-factory>

</hibernate-configuration>

测试代码:

packageVersion;


importjava.io.File;
importjava.util.Iterator;
importjava.util.Set;

importorg.hibernate.Session;
importorg.hibernate.SessionFactory;
importorg.hibernate.Transaction;
importorg.hibernate.cfg.Configuration;

publicclassTest{


publicstaticvoidmain(String[]args){

StringfilePath
=System.getProperty("user.dir")+File.separator+"src/Version"+File.separator+"hibernate.cfg.xml";
Filefile
=newFile(filePath);
System.out.println(filePath);
SessionFactorysessionFactory
=newConfiguration().configure(file).buildSessionFactory();
Sessionsession
=sessionFactory.openSession();
Transactiont
=session.beginTransaction();

Studentstu
=newStudent();
stu.setName(
"tom11");
session.save(stu);
t.commit();


/*
*模拟多个session操作student数据表
*/


Sessionsession1
=sessionFactory.openSession();
Sessionsession2
=sessionFactory.openSession();
Studentstu1
=(Student)session1.createQuery("fromStudentswheres.name='tom11'").uniqueResult();
Studentstu2
=(Student)session2.createQuery("fromStudentswheres.name='tom11'").uniqueResult();

//这时候,两个版本号是相同的
System.out.println("v1="+stu1.getVersion()+"--v2="+stu2.getVersion());

Transactiontx1
=session1.beginTransaction();
stu1.setName(
"session1");
tx1.commit();
//这时候,两个版本号是不同的,其中一个的版本号递增了
System.out.println("v1="+stu1.getVersion()+"--v2="+stu2.getVersion());

Transactiontx2
=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

分享到:
评论

相关推荐

    乐观锁version-练习

    2. **Hibernate的乐观锁机制**:了解Hibernate如何通过`version`字段实现乐观锁,包括`@Version`注解的使用、对象状态管理及冲突检测。 3. **乐观锁与悲观锁的区别**:对比两种锁的优缺点,例如悲观锁的资源消耗大...

    Hibernate悲观锁和乐观锁的实现

    在Hibernate中,乐观锁通常通过版本字段(version)或者时间戳(timestamp)实现: 1. **Version字段**:每个记录都有一个版本号字段,每次更新时会自动递增。如果更新时发现版本号与数据库中的不一致,那么更新...

    Hibernate乐观锁和悲观锁分析

    Hibernate通过版本字段(Version)实现乐观锁,具体步骤如下: 1. 在实体类的`class`标签中添加`optimistic-lock="version"`属性,表示启用乐观锁。 2. 在`hibernate.cfg.xml`或`entity.hbm.xml`中,紧随`id`标签后...

    Hibernate的乐观锁与悲观锁

    **Hibernate**作为一种流行的Java持久层框架,提供了多种机制来处理并发控制问题,其中最常用的就是**乐观锁**和**悲观锁**。本文将详细介绍这两种锁的原理、应用场景以及如何在Hibernate中实现。 #### 二、悲观锁...

    hibernate乐观锁和悲观锁学习

    在Hibernate中,通常通过在实体类的映射文件中设置`optimistic-lock`属性来实现乐观锁,比如设置为`version`,这将利用数据库的版本字段来检测并发冲突。当尝试更新时,如果发现版本号已变,说明有其他事务进行了...

    Hibernate version 乐观锁 (xml方式)

    本文将深入探讨 Hibernate 版本的乐观锁机制,特别是通过XML配置方式实现这一机制。乐观锁是一种非阻塞锁,它假设在并发环境下数据冲突的概率较低,因此在读取数据时不加锁,而在更新数据时检查在此期间是否有其他...

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

    Hibernate 中的乐观锁实现方式可以通过在对象中增加一个 version 属性来实现版本号控制锁定。例如: ```java public class Account { private int version; .... public void setVersion(int version) { this....

    hibernate的乐观锁和悲观锁

    **Hibernate中的乐观锁实现**: 在Hibernate中,可以通过配置文件或注解的方式指定实体类的乐观锁策略。例如,使用版本号字段: ```java @Entity @Table(name = "account") public class Account { @Id @...

    Hibernate乐观锁

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

    Hibernate悲观锁与乐观锁

    总结来说,Hibernate的悲观锁和乐观锁是两种不同的并发控制策略,悲观锁倾向于预防并发冲突,适合并发较低但需要保证数据一致性的情景;而乐观锁则在并发较高的情况下更优,通过版本控制减少锁定,但在冲突处理上...

    (5)Hibernate中的many-to-many和并发

    在Hibernate中,可以使用`@Version`注解来实现乐观锁。每次更新实体时,Hibernate会检查版本号是否匹配。如果版本不匹配,更新会被回滚,从而防止丢失更新。 ```java @Entity @org.hibernate.annotations.Cache...

    Hibernate悲观锁与乐观锁案例

    在Java的持久化框架Hibernate中,悲观锁和乐观锁是两种重要的并发控制策略,它们用于管理数据库中的数据在多线程环境下的访问安全。本文将深入探讨这两种锁机制的原理、应用场景及其区别。 首先,我们来理解悲观锁...

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

    在Hibernate中,可以使用`@Version`注解来实现乐观锁,该注解会在实体类的一个属性上添加版本字段,每次更新时,Hibernate会比较当前版本号和数据库中的版本号,如果不同,则认为有并发冲突,更新失败。乐观锁的优点...

    Hibernate 事务和并发控制

    在Hibernate中,可以通过在实体类的属性上添加@Version注解来实现乐观锁。 悲观锁则是在数据读取时就立即加锁,直到事务结束才释放,确保了其他事务在此期间无法修改数据。Hibernate提供了LockMode类型的锁,如...

    Hibernate事务和并发控制

    Hibernate提供了多种并发策略,如版本字段(version)和时间戳(timestamp),以实现乐观锁。在更新数据时,Hibernate会检查版本号或时间戳,如果发现有其他事务在此期间也修改了数据,就会抛出并发异常,从而避免...

    Java 中的悲观锁和乐观锁的实现

    在这个例子中,`@Version`注解表示该字段用于实现乐观锁。当尝试更新记录时,Hibernate会检查版本号是否发生变化,如果发生变化则抛出异常。 **3. 乐观锁的优势与局限** - **优势**:乐观锁避免了长时间锁定数据的...

    Hibernate 乐观和悲观锁

    在Hibernate中,乐观锁通常通过版本号(Version)或时间戳(Timestamp)来实现。当多个事务尝试更新同一条记录时,如果某个事务的版本号与数据库中的不匹配,那么更新会被拒绝。这样可以避免锁竞争,提高并发性能,...

    Hibernate中,利用版本管理机制来控制事务并发

    在Java的持久化框架Hibernate中,版本管理机制是实现事务并发控制的重要手段。它通过维护对象的版本信息,确保在多线程环境下数据的一致性和完整性。本文将深入探讨Hibernate中的版本管理机制及其在控制事务并发中的...

    J2EE事务并发控制策略总结汇编.pdf

    - Hibernate支持自动的乐观锁管理,通过@Entity注解的@Version字段,Hibernate会在提交时自动处理版本号比较和更新。 此外,还有其他的并发控制策略,如行级锁定、两阶段锁定、多版本并发控制(MVCC)等。在实际应用...

Global site tag (gtag.js) - Google Analytics