通过在表中及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&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,作为Java领域广泛使用的ORM框架,提供了一种处理并发数据访问冲突的手段,那就是锁机制。主要...
Hibernate乐观锁是数据库事务控制的一种策略,主要用于处理并发更新数据的情况。在乐观锁的机制下,假设并发用户很少会发生冲突,所以在读取数据时不会进行任何锁定,而在更新数据时才会检查在此期间是否有其他用户...
本文主要讨论的是Hibernate框架中两种锁机制的使用:乐观锁和悲观锁。 首先,让我们深入理解悲观锁(Pessimistic Locking)。悲观锁正如其名字所示,假设并发环境中数据会被频繁修改,所以在整个数据处理过程中,它...
在Hibernate源码中,乐观锁的实现主要依赖于`AbstractEntityPersister`类的`checkOptimisticLocking()`方法,它会比较当前对象的版本信息与数据库中的版本信息,如果不同则抛出`StaleObjectStateException`异常。...
### Hibernate的乐观锁与悲观锁 #### 一、引言 在并发环境下,尤其是在金融、电商等业务场景中,确保数据的一致性和完整性至关重要。**Hibernate**作为一种流行的Java持久层框架,提供了多种机制来处理并发控制...
标题中的“Hibernate 乐观和悲观锁”涉及到的是Java领域中持久化框架Hibernate中的一种数据并发控制策略。在多线程环境下,为了保证数据的一致性和完整性,数据库管理系统提供了多种锁定机制,其中乐观锁和悲观锁是...
### Hibernate的乐观锁和悲观锁 #### 一、引言 在软件开发中,尤其是在涉及大量并发操作的应用场景下,确保数据的一致性和完整性是非常重要的。对于基于Java Web的应用而言,Hibernate作为一款流行的ORM框架,提供...
乐观锁 求助编辑百科名片相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库 性能的大量开销,特别是对长事务而...
在了解了Hibernate乐观锁的XML配置后,我们可以结合源码进一步分析其实现细节。在Hibernate中,乐观锁的处理主要在`org.hibernate.event.internal.DefaultMergeEventListener`和`org.hibernate.event.internal....
整体来看,本手册为Hibernate5的使用者提供了详尽的指导,从基础架构开始,到具体的编程实践,再到性能优化和高级特性,覆盖了使用Hibernate进行Java持久化编程所需的所有知识点。对于初学者而言,是学习Hibernate的...
Hibernate 锁机制是指在数据库访问中,为了维护数据的一致性和正确性,所采取的一些机制来防止数据的并发访问和修改。 Hibernate 中有两种锁机制:悲观锁和乐观锁。 一、悲观锁(Pessimistic Locking) 悲观锁是一...
4. **Hibernate乐观锁实现**:在Hibernate中,可以通过在实体类上添加`@Version`注解来启用乐观锁,该注解对应的字段会在数据库中自动生成并维护。在更新时,Hibernate会自动处理版本号的比较和更新。 5. **配置...
在《hibernate_3200_Concurrency_Pessimistic_Lock》这个压缩包中,很可能包含了关于Hibernate框架如何实现悲观锁和乐观锁的详细资料,包括源代码示例、配置方法和使用场景。通过学习这些资料,你可以深入了解这两种...
例如,以下代码展示了如何在Hibernate中使用悲观锁: ```java Query query = session.createQuery("from User user"); query.setLockMode("user", LockMode.UPGRADE); ``` 这段代码在执行查询前,通过`setLockMode...
总的来说,Hibernate的悲观锁和乐观锁是处理并发问题的重要工具,开发者需要根据实际情况权衡性能和数据一致性,合理选择并使用合适的锁策略。在实际项目中,还可以结合使用其他的并发控制手段,如事务隔离级别、...
以上只是Hibernate众多知识点的一部分,实际面试中可能涉及更多细节,如级联操作、事务隔离级别、延迟加载机制、乐观锁和悲观锁的区别等。熟悉并理解这些内容对于通过Hibernate相关的面试至关重要。
- `@Version`: 用于实现乐观锁机制,通常与版本字段一起使用,每次更新数据时,会检查此字段是否与数据库中的值一致,确保数据一致性。 - `@Column`: 用于将实体的属性映射到数据库表的列,可以自定义列的名称、...
这个中文帮助文档详细介绍了如何使用Hibernate的注解来配置实体Bean,实现与数据库的无缝对接。 1. 创建注解项目: 在开始使用Hibernate的注解之前,你需要满足一定的系统需求,包括JDK、Hibernate库以及兼容的...
#### Hibernate所需类库 在使用Hibernate之前,需要确保系统中已经安装了JDBC驱动程序,这是为了能够与关系数据库进行通信。对于MySQL用户,需要从MySQL官网下载相应的JDBC驱动。此外,还需要下载Hibernate的最新...