Hibernate中的悲观锁与乐观锁
来源:互联网 发布:淘宝网中老年冬装 编辑:程序博客网 时间:2024/06/05 13:40
(一).悲观锁的概念
1.Hibernate悲观锁:在数据有加载的时候就给其进行加锁,直到该锁被释放掉,其他用户才可以进行修改,优点:数据的一致性保持得很好,缺点:不适合多个用户并发访问。当一个锁住的资源不被释放掉的时候,这个资源永远不会被其他用户进行修改,容易造成无限期的等待。
悲观锁的加锁模式有:
LockMode.NONE:无锁机制
- LockMode.WRITE:Hibernate在Insert和Update记录的时候会自动获取
- LockMode.READ:Hibernate在读取记录的时候会自动获取
- LockMode.UPGRADE:利用数据库的for update子句加锁
(二) 乐观锁的概念
- Hibernate乐观锁:就是在对数据进行修改的时候,对数据才去版本或者时间戳等方式来比较,数据是否一致性来实现加锁。优点比较好。
- 乐观锁加锁模式有:
- none:无乐观锁
- version:通过版本机制实现乐观锁
- dirty:通过检查发生变动过的属性实现乐观锁
- all:通过检查所有属性实现乐观锁
(三)悲观锁的实例代码
package cn.codeWang.entity;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;@Entity(name = "person")public class Person { @Id @GeneratedValue private int id; private String name; private String sex; private String department; public Person() { } public Person(String name, String sex, String department) { super(); this.name = name; this.sex = sex; this.department = department; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; }}<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration> <session-factory> <!-- 配置连接数据库 --> <property name="connection.username">root</property> <property name="connection.password">root</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql:///hibernate1?useUnicode=true&characterEncoding=UTF-8</property> <!-- 配置方言是非常重要!!!我这里配置的为MySQL5Dialect --> <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- 配置C3P0连接池 --> <property name="hibernate.c3p0.max_size">200</property> <property name="hibernate.c3p0.min_size">2</property> <property name="hibernate.c3p0.max_statements">50</property> <property name="hibernate.c3p0.timeout"></property> <property name="show_sql">true</property> <property name="format_sql">true</property> <property name="hbm2ddl.auto">update</property> <!-- 配置映射文件 --> <mapping class="cn.codeWang.entity.Person"/> </session-factory></hibernate-configuration>
1.模拟两个人向同一数据库修改数据,这里我使用了悲观锁,看看它的作用是什么?import java.util.Iterator;import java.util.List;import org.hibernate.LockOptions;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.boot.MetadataSources;import org.hibernate.boot.registry.StandardServiceRegistryBuilder;import org.hibernate.service.ServiceRegistry;import org.junit.After;import org.junit.Before;import org.junit.Test;import cn.codeWang.entity.Person;public class DemoTest { private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before public void init() { // 创建服务注册对象 ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build(); // 创建会话工厂对象 sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory(); // 会话对象 session = sessionFactory.openSession(); // 开启事物 transaction = session.beginTransaction(); } @After public void destory() { // 提交事物 transaction.commit(); // 关闭会话 session.close(); // 关闭会话工厂 sessionFactory.close(); } @Test public void TestLock(){ Person p1=session.get(Person.class, 2, LockOptions.UPGRADE ); System.out.println(p1.getName()); p1.setName("李四"); session.update(p1); //第二次获得session对象 Session session = sessionFactory.openSession(); Person p2=session.get(Person.class, 2); System.out.println(p2.getName()); p2.setName("曹操"); session.update(p2); }}控制台输出结果为:Hibernate: select person0_.id as id1_0_0_, person0_.department as departme2_0_0_, person0_.name as name3_0_0_, person0_.sex as sex4_0_0_ from person person0_ where person0_.id=?李四Hibernate: select person0_.id as id1_0_0_, person0_.department as departme2_0_0_, person0_.name as name3_0_0_, person0_.sex as sex4_0_0_ from person person0_ where person0_.id=?李四总结: 第一个session对象调用get()方法使用了悲观锁机制,可以对对象实现更新操作。但是第二person对象无法对数据库进行更新操作(delete、update、insert)。只能对数据库进行读取操作。
4.乐观锁实例代码
package cn.codeWang.entity;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Version;@Entity(name = "person")public class Person { @Id @GeneratedValue private int id; @Version private int version; private String name; private String sex; private String department; public Person() { } public Person(String name, String sex, String department) { super(); this.name = name; this.sex = sex; this.department = department; } public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; }}
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration> <session-factory> <!-- 配置连接数据库 --> <property name="connection.username">root</property> <property name="connection.password">root</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql:///hibernate1?useUnicode=true&characterEncoding=UTF-8</property> <!-- 配置方言是非常重要!!!我这里配置的为MySQL5Dialect --> <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- 配置C3P0连接池 --> <property name="hibernate.c3p0.max_size">200</property> <property name="hibernate.c3p0.min_size">2</property> <property name="hibernate.c3p0.max_statements">50</property> <property name="hibernate.c3p0.timeout"></property> <property name="show_sql">true</property> <property name="format_sql">true</property> <property name="hbm2ddl.auto">update</property> <!-- 配置映射文件 --> <mapping class="cn.codeWang.entity.Person"/> </session-factory></hibernate-configuration>
import java.util.Iterator;import java.util.List;import org.hibernate.LockOptions;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.boot.MetadataSources;import org.hibernate.boot.registry.StandardServiceRegistryBuilder;import org.hibernate.service.ServiceRegistry;import org.junit.After;import org.junit.Before;import org.junit.Test;import cn.codeWang.entity.Person;public class DemoTest { private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before public void init() { // 创建服务注册对象 ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build(); // 创建会话工厂对象 sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory(); // 会话对象 session = sessionFactory.openSession(); // 开启事物 transaction = session.beginTransaction(); } @After public void destory() { // 提交事物 transaction.commit(); // 关闭会话 session.close(); // 关闭会话工厂 sessionFactory.close(); } @Test // 筛选需要的数据 public void testSaveDate() { Person p1 = new Person("凯耐", "男", "生产部"); Person p2 = new Person("凯丽", "女", "管理部"); Person p3 = new Person("欧陆", "男", "营销部"); session.save(p1); session.save(p2); session.save(p3); } @Test public void testOptimistic() { Person p = session.get(Person.class, 2); p.setName("赵本山"); session.update(p); System.out.println("姓名=" + p.getName()); session = sessionFactory.openSession(); p = session.get(Person.class, 2); p.setName("飞机"); session.update(p); System.out.println("姓名=" + p.getName()); }}
控制台输出结果为:
Hibernate:
select
person0_.id as id1_0_0_,
person0_.department as departme2_0_0_,
person0_.name as name3_0_0_,
person0_.sex as sex4_0_0_,
person0_.version as version5_0_0_
from
person person0_
where
person0_.id=?
姓名=赵本山
姓名=飞机
Hibernate:
update
person
set
department=?,
name=?,
sex=?,
version=?
where
id=?
and version=?
总结:使用乐观锁不同的session可以并发的对同一对象数据进行修改!
- hibernate中的悲观锁与乐观锁
- Hibernate中的悲观锁与乐观锁
- Hibernate中的悲观锁与乐观锁
- HIbernate中的乐观锁与悲观锁
- Hibernate中的悲观锁与乐观锁
- hibernate中的悲观锁与乐观锁(转…
- hibernate中的悲观锁和乐观锁
- hibernate中的悲观锁和乐观锁
- hibernate中的悲观锁和乐观锁
- Hibernate 中的悲观锁和乐观锁
- Hibernate中的乐观锁和悲观锁
- hibernate中的乐观锁和悲观锁
- hibernate中的乐观锁和悲观锁
- Hibernate中的悲观锁和乐观锁
- hibernate中的悲观锁和乐观锁
- Hibernate的乐观锁与悲观锁
- Hibernate的乐观锁与悲观锁
- Hibernate悲观锁与乐观锁
- 8.14 免费的午餐 2692
- C++ SetTimer
- [bzoj1854][Scoi2010]游戏
- sin之舞
- openGL坐标系
- Hibernate中的悲观锁与乐观锁
- Android TelephonyManager 监听手机来电
- [BZOJ3390]荒岛野人
- 1055. The World's Richest (25)
- UVA 272 TEX Quotes
- mysql grant
- Mybatis-Generator自动生成代码——Mybatis 深入浅出(二)
- 深度理解链式前向星(转载于ACdreamer大神)
- MJPG-streamer源码分析-主函数部分