`

Hibernate 乐观锁实现----version

阅读更多


乐观并发控制,可以有三种方式。

1,Version版本号

2,时间戳

3,自动版本控制。

这里不建议在新的应用程序中定义没有版本或者时间戳列的版本控制:它更慢,更复杂,如果你正在使用脱管对象,它则不会生效。





以下信息来自 : http://esffor.iteye.com/blog/168243

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

数据库脚本:

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



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;
}


}



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" >
    <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>



Hibernate.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.dialect">
        org.hibernate.dialect.MySQLDialect
    </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>


测试代码:



package Version;


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的version属性,使之与资料库中的版本号相同的话就不会有错误,像这样版本号被更改,或是由于资料是由外部系统而来,因而版本资讯不受控制时,锁定机制将会有问题,设计时必须注意。

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


注:::本文转自http://zdq0426.blog.163.com/blog/static/2216909420091017113427971/
分享到:
评论

相关推荐

    乐观锁version-练习

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

    Hibernate乐观锁和悲观锁分析

    【Hibernate乐观锁与悲观锁详解】 在开发过程中,尤其是在并发环境下,确保数据的一致性和完整性至关重要。Hibernate,作为Java领域广泛使用的ORM框架,提供了一种处理并发数据访问冲突的手段,那就是锁机制。主要...

    Hibernate悲观锁和乐观锁的实现

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

    Hibernate乐观锁

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

    hibernate乐观锁和悲观锁学习

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

    Hibernate version 乐观锁 (xml方式)

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

    Hibernate的乐观锁与悲观锁

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

    hibernate的乐观锁和悲观锁

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

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

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

    Hibernate悲观锁与乐观锁

    Hibernate推荐的乐观锁实现是通过在实体类中添加一个版本字段,每次数据更新时,若版本号与数据库中的版本号匹配,更新成功并递增版本号;若不匹配,则表示数据已被其他用户修改,更新操作将失败。这通常通过`...

    Hibernate悲观锁与乐观锁案例

    在Hibernate中,乐观锁通常通过版本字段(version)或者时间戳(timestamp)实现。当多个线程尝试同时更新同一数据时,只有版本号或时间戳匹配的更新才能成功,其他不匹配的更新会被回滚。这种方式减少了锁的使用,...

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

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

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

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

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

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

    Hibernate3个jar包

    例如,@GeneratedValue可以帮助我们自动生成主键值,@Temporal用于处理日期和时间类型,@Version则实现了乐观锁机制,确保并发访问时的数据一致性。 这三个库文件共同构成了Hibernate ORM的核心组件,使得开发者...

    hibernate-annotations-3.4.0.GA

    `@Version`注解用于实现乐观锁,防止并发更新时的数据冲突。 总结,Hibernate Annotations 3.4.0.GA版本提供了丰富的注解,使得开发人员可以轻松地在Java类中定义和管理数据库实体,降低了数据库操作的复杂度,...

    Hibernate 乐观和悲观锁

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

    hibernate-annotations-3.0-alpha3.zip

    - @Version:用于乐观锁,控制并发更新时的数据版本。 - @Cacheable与@Cache:支持二级缓存,提高数据访问速度。 6. **包lib**: 压缩包中的`lib`目录包含了Hibernate Annotations运行所需的依赖库,如Hibernate...

    hibernate5--2.数据持久化及事务

    Hibernate通过`@Version`注解实现乐观锁。 - **悲观锁**:在读取数据时就锁定资源,防止其他事务修改,直至事务结束释放锁。Hibernate通过`@Lock`注解配合`LockModeType`实现悲观锁。 **5. 事务的回滚规则** - ...

Global site tag (gtag.js) - Google Analytics