并发访问
可能引发的问题:更新丢失
(A线程把name属性改了,B线程马上改age属性,但是B线程中的name属性仍然是改之前的值,这就造成了A线程对name的更新丢失了)
------------------------
解决方案
*悲观锁 LockOptions.UPGRADE 虽然可以保证多线程下并发访问数据不会造成数据混乱---for update
但是,锁定记录的规则太不灵活,不建议使用
[一旦被某个线程锁定,其它线程无法进行,将被挂起,直到其释放锁其它线程才能进入]
行级锁,当A线程在更新此行时,其它线程无法查询到此行的数据,只有等到A线程操作完成,其它线程才能对该行进行查询,这样其它线程查询到的结果就是A线程更新后的结果!
------------------------
*乐观锁 (解决并发访问通用方法!)
<!-- 版本标识,用于解决并发访问 -->
<version name="versionNumber"></version>
定义在<id></id>与<property></property>之间
实体类中添加属性 private int versionNumber;
数据库中该字段的值由hibernate维护,程序员不用管理;
好处:提高性能,避免死锁
对于读操作没有限制,即读操作线程不受限制
通过比较线程所操纵的版本号与数据库记录的版本号是否一致来决定更新是否成功
版本号相同的记录才能被更新,
否则更新失败,抛出异常 Row was updated or deleted by another transaction
可以在捕获异常的时候,转化异常为"更新失败",提示重新更新
package org.leadfar.hibernate.model; import java.util.Set; public class Group { private int id; private String name; private Set<ContactPerson> persons; public Set<ContactPerson> getPersons() { return persons; } public void setPersons(Set<ContactPerson> persons) { this.persons = persons; } public Group() { // TODO Auto-generated constructor stub } public Group(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.auction"> <!-- name为实体类 table为映射到数据库中的表 lazy默认为true 延迟发出select语句,直到真正用到对象的属性(非id属性)--> <class name="org.leadfar.hibernate.model.Group" table="t_group" batch-size="25"> <!-- id为数据库标识,作为主键 --> <id name="id"> <generator class="native"/> </id> <property name="name"/> <!-- <set name="persons" fetch="select" batch-size="20"> <key column="gid"></key> <one-to-many class="org.leadfar.hibernate.model.ContactPerson"/> </set> --> <set name="persons" fetch="subselect"> <key column="gid"></key> <one-to-many class="org.leadfar.hibernate.model.ContactPerson"/> </set> </class> </hibernate-mapping>
package org.leadfar.hibernate.model; import java.util.Date; public class ContactPerson { private int id; private String name; private int age; private Date birthday; private Group group; private int versionNumber;//版本字段 public ContactPerson() { } public ContactPerson(String name) { this.name = name; } public ContactPerson(int id,String name) { this.id = id; this.name = name; } public ContactPerson(int id,int age,String name) { this.id = id; this.age = age; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Group getGroup() { return group; } public void setGroup(Group group) { this.group = group; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public int getVersionNumber() { return versionNumber; } public void setVersionNumber(int versionNumber) { this.versionNumber = versionNumber; } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.auction"> <!-- name为实体类 table为映射到数据库中的表 lazy默认为true 延迟发出select语句,直到真正用到对象的属性(非id属性)--> <class name="org.leadfar.hibernate.model.ContactPerson" table="t_person"> <id name="id"> <generator class="native"/> </id> <!-- 版本标识,用于解决并发访问 --> <version name="versionNumber"></version> <property name="name"/> <property name="age"></property> <property name="birthday" type="date"></property> <many-to-one name="group" column="gid" fetch="join"></many-to-one> </class> </hibernate-mapping>
测试
package org.leadfar.hibernate.model; import java.util.Date; import java.util.List; import java.util.Random; import java.util.Set; import junit.framework.TestCase; import org.hibernate.LockOptions; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class TestHQL extends TestCase { public void save_person() throws Exception { Configuration cfg = new Configuration().configure(); SessionFactory sfactory = cfg.buildSessionFactory(); Session session = sfactory.openSession(); try { //开启事务 session.beginTransaction(); Random r = new Random(); for(int i=0;i<100;i++) { Group g = new Group("组"+i); session.save(g); ContactPerson cp = new ContactPerson("用户"+i); cp.setAge(r.nextInt(99)); cp.setBirthday(new Date()); cp.setGroup(g); session.save(cp); } //提交事务 session.getTransaction().commit(); } catch(Exception e) { e.printStackTrace(); //出现异常,回滚事务 session.getTransaction().rollback(); } finally { //关闭session session.close();//session关闭之后,user对象处于离线Detached状态 } } /** * 悲观锁 upgrade * 利用数据库对记录进行锁定,需要等待更新操作完成后才能对其进行读取和更新 */ public void lock_upgrade_01() throws Exception { Configuration cfg = new Configuration().configure(); SessionFactory sfactory = cfg.buildSessionFactory(); Session session = sfactory.openSession(); try { session.beginTransaction(); ContactPerson cp = (ContactPerson)session.get(ContactPerson.class, 100,LockOptions.UPGRADE); System.out.println(cp.getName()); cp.setName("AA"); session.getTransaction().commit(); } catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally { session.close(); } } public void lock_upgrade_02() throws Exception { Configuration cfg = new Configuration().configure(); SessionFactory sfactory = cfg.buildSessionFactory(); Session session = sfactory.openSession(); try { session.beginTransaction(); ContactPerson cp = (ContactPerson)session.get(ContactPerson.class, 100,LockOptions.UPGRADE); System.out.println(cp.getName()); cp.setAge(101); session.getTransaction().commit(); } catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally { session.close(); } } /** * 乐观锁 */ public void lock_optimism_01() throws Exception { Configuration cfg = new Configuration().configure(); SessionFactory sfactory = cfg.buildSessionFactory(); Session session = sfactory.openSession(); try { session.beginTransaction(); ContactPerson cp = (ContactPerson)session.get(ContactPerson.class, 100); System.out.println(cp.getName()); cp.setName("BB"); session.getTransaction().commit(); } catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally { session.close(); } } public void lock_optimism_02() throws Exception { Configuration cfg = new Configuration().configure(); SessionFactory sfactory = cfg.buildSessionFactory(); Session session = sfactory.openSession(); try { session.beginTransaction(); ContactPerson cp = (ContactPerson)session.get(ContactPerson.class, 100); System.out.println(cp.getName()); cp.setAge(88); session.getTransaction().commit(); } catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally { session.close(); } } }
相关推荐
其中通过 version 实现的乐观锁机制是 Hibernate 官方推荐的乐观锁实现,同时也是 Hibernate 中,目前唯一在数据对象脱离 Session 发生修改的情况下依然有效的锁机制。因此,一般情况下,我们都选择 version 方式...
Hibernate的乐观锁与悲观锁的文档,帮助学习Hibernate的乐观锁与悲观锁,让你们学得更轻松。
hibernate配置文件 里面提供了连接数据库 数据库使用的方言 是否打印SQL语句 sql语句的格式 以及对象-关系映射文件的地址等
spring整合struts2与hibernate核心配置文件
Hibernate乐观锁和悲观锁分析,针对在使用HIBERNATE时怎么配置乐观锁进行了详细的范例讲解
hibernate配置,详细的讲了hibernate用的配置文件和方法,可以哦
Hibernate核心配置文件在配置的时候有很多需要配置的内容,比如数据库地址,用户名,密码等。在这张对照表里面都能找到。
逆向生成hibernate配置文件逆向生成hibernate配置文件逆向生成hibernate配置文件逆向生成hibernate配置文件逆向生成hibernate配置文件逆向生成hibernate配置文件
这是最新的hibernate的下载和安装包。hibernate配置文件主要是用于配置数据库连接、事务管理,以及指定hibernate本省的配置信息和hibernate的映射文件信息。
Hibernate学习的必备,包含了Hibernate的配置文件,MySQL的连接jar文件
在myeclipse中配置hibernate 自动生成配置文件在myeclipse中配置hibernate 自动生成配置文件
hibernate利用配置文件,实体关系数据库映射文件及数据库配置相关文件) 反向生成数据库所有配置文件, 及其所需的几个文件所有详细代码
在 javaweb 开发时会用到三大框架ssh 其中hibernate的使用要先配置一下映射的文件,你可以通过下载此代码作为参考
关于hibernate的配置文件hibernate1.cfg.xml
《Hibernate 各类映射文件与配置文件模板》HibernateMappingConfig.zip
Hibernate配置文件Hibernate配置文件Hibernate配置文件
博文链接:https://sydxide2006.iteye.com/blog/127824
hibernate--5.Hibernate配置文件详解
Hibernate配置文件hibernate.cfg.xml中配置信息详解!
Hibernate自动生成配置文件(配图)