HIbernate学习笔记(九) hibernate事务并发处理与乐观悲观锁
事务并发处理
一、 数据库的隔离级别:并发性作用。
1、 ReadUncommited(未提交读):没有提交就可以读取到数据(发出了Insert,但没有commit就可以读取到。)很少用
2、 ReadCommited(提交读):只有提交后才可以读,常用,
3、 RepeatableRead(可重复读):mysql默认级别, 必需提交才能见到,读取数据时数据被锁住。
4、 Serialiazble(序列化读):最高隔离级别,串型的,你操作完了,我才可以操作,并发性特别不好,
|
隔离级别 |
是否存在脏读 |
是否存在不可重复读 |
是否存在幻读 |
|
Read Uncommitted(未提交读) |
Y |
Y |
Y |
|
Read Commited(提交读) |
N |
Y(可采用悲观锁解决) |
Y |
|
Repeatable Read(可重复读) |
N |
N |
Y |
|
Serialiazble(序列化读) |
脏读:没有提交就可以读取到数据称为脏读
不可重复读:再重复读一次,数据与你上的不一样。称不可重复读。
幻读:在查询某一条件的数据,开始查询的后,别人又加入或删除些数据,再读取时与原来的数据不一样了。
1、 Mysql查看数据库隔离级别:
方法:select@@tx_isolation;

2、 Mysql数据库修改隔离级别:
方法:set transactionisolation level 隔离级别名称;
例如:修改为未提交读:settransaction isolation level read uncommitted;

二、 事务概念(ACID)
ACID即:事务的原子性、一致性、独立性及持久性
事务的原子性:是指一个事务要么全部执行,要么不执行.也就是说一个事务不可能只执行了一半就停止了.比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱.不可能划了卡,而钱却没出来.这两步必须同时完成.要么就不完成.
事务的一致性:是指事务的运行并不改变数据库中数据的一致性.例如,完整性约束了a+b=10,一个事务改变了a,那么b也应该随之改变.
事务的独立性:是指两个以上的事务不会出现交错执行的状态.因为这样可能会导致数据不一致.
事务的持久性:是指事务运行成功以后,就系统的更新是永久的.不会无缘无故的回滚.
三、 事务并发时可能出现问题
1、第一类丢失更新(Lost Update)
|
时间 |
||
hibernate悲观锁、乐观锁
Hibernate谈到悲观锁、乐观锁,就要谈到数据库的并发问题,数据库的隔离级别越高它的并发性就越差
并发性:当前系统进行了序列化后,当前读取数据后,别人查询不了,看不了。称为并发性不好
数据库隔离级别:见前面章级
一、 悲观锁
悲观锁:具有排他性(我锁住当前数据后,别人看到不此数据)
悲观锁一般由数据机制来做到的。
1、 悲观锁的实现
通常依赖于数据库机制,在整修过程中将数据锁定,其它任何用户都不能读取或修改(如:必需我修改完之后,别人才可以修改)
2、 悲观锁的适用场景:
悲观锁一般适合短事务比较多(如某一数据取出后加1,立即释放)
长事务占有时间(如果占有1个小时,那么这个1小时别人就不可以使用这些数据),不常用。
3、 实例:

yon
用户1、用户2 同时读取到数据,但是用户2先 -200,这时数据库里的是800,现在用户1也开始-200,可是用户1刚才读取到的数据是1000,现在用户用刚刚一开始读取的数据1000-200为800,而用户1在更新时数据库里的是用房更新的数据800,按理说用户1应该是800-200=600,而现在是800,这样就造成的更新丢失。这种情况该如何处理呢,可采用两种方法:悲观锁、乐观锁。先看看悲观锁:用户1读取数据后,用锁将其读取的数据锁上,这时用户2是读取不到数据的,只有用户1释放锁后用户2才可以读取,同样用户2读取数据也锁上。这样就可以解决更新丢失的问题了。
实体类:
public class Inventory {
private int itemNo;
privateString itemName;
private int quantity;
public intgetItemNo() {
return itemNo;
}
public voidsetItemNo(intitemNo) {
this.itemNo =itemNo;
}
publicString getItemName() {
return itemName;
}
public voidsetItemName(String itemName) {
this.itemName =itemName;
}
public intgetQuantity() {
return quantity;
}
public voidsetQuantity(intquantity) {
this.quantity =quantity;
}
}
映射文件:
<hibernate-mapping>
<class name="com.wjt276.hibernate.Inventory"table="t_inventory">
<id name="itemNo">
<generator class="native"/>
</id>
<property name="itemName"/>
<property name="quantity"/>
</class>
</hibernate-mapping>
4、 悲观锁的使用
如果需要使用悲观锁,肯定在加载数据时就要锁住,通常采用数据库的for update语句。
Hibernate使用Load进行悲观锁加载。
Session.load(Classarg0, Serializable arg1, LockMode arg2) throws HibernateException
LockMode:悲观锁模式(一般使用LockMode.UPGRADE)
session= HibernateUtils.getSession();
tx = session.beginTransaction();
Inventory inv =(Inventory)session.load(Inventory.class, 1,LockMode.UPGRADE);
System.out.println(inv.getItemName());
inv.setQuantity(inv.getQuantity()-200);
session.update(inv);
tx.commit();
5、 执行输出SQL语句:
Hibernate:select inventory0_.itemNo as itemNo0_0_, inventory0_.itemName as itemName0_0_,inventory0_.quantity as quantity0_0_ from t_inventory inventory0_ where inventory0_.itemNo=?for update //在select语句中加入for update进行使用悲观锁。
脑白金
Hibernate:update t_inventory set itemName=?, quantity=? where itemNo=?
注:只有用户释放锁后,别的用户才可以读取
注:如果使用悲观锁,那么lazy(悚加载无效)
二、 乐观锁
乐观锁:不是锁,是一种冲突检测机制。
乐观锁的并发性较好,因为我改的时候,别人随边修改。
乐观锁的实现方式:常用的是版本的方式(每个数据表中有一个版本字段version,某一个用户更新数据后,版本号+1,另一个用户修改后再+1,当用户更新发现数据库当前版本号与读取数据时版本号不一致(等于小于数据库当前版本号),则更新不了。
Hibernate使用乐观锁需要在映射文件中配置项才可生效。
实体类:
public classInventory {
private int itemNo;
privateString itemName;
private int quantity;
private int version;//Hibernate用户实现版本方式乐观锁,但需要在映射文件中配置
public intgetItemNo() {
return itemNo;
}
public voidsetItemNo(intitemNo) {
this.itemNo =itemNo;
}
publicString getItemName() {
return itemName;
}
public voidsetItemName(String itemName) {
this.itemName =itemName;
}
public intgetQuantity() {
return quantity;
}
public voidsetQuantity(intquantity) {
this.quantity =quantity;
}
public intgetVersion() {
return version;
}
public voidsetVersion(intversion) {
this.version =version;
}
}
映射文件
<hibernate-mapping>
<!-- 映射实体类时,需要加入一个开启乐观锁的属性
optimistic-lock="version" 共有好几种方式:
- none -version - dirty - all
同时需要在主键映射后面映射版本号字段
-->
<class name="com.wjt276.hibernate.Inventory"table="t_inventory"optimistic-lock="version">
<id name="itemNo">
<generator class="native"/>
</id>
<version name="version"/><!—必需配置在主键映射后面 -->
<property name="itemName"/>
<property name="quantity"/>
</class>
</hibernate-mapping>
导出输出SQL语句:
createtable t_inventory (itemNo integer not null auto_increment, versioninteger not null, itemName varchar(255), quantity integer,primary key (itemNo))
注:添加的版本字段version,还是我们来维护的,是由hibernate来维护的。
乐观锁在存储数据时不用关心
HIbernate学习笔记(九) hibernate事务并发处理与乐观悲观锁的更多相关文章
- hibernate学习笔记之四 Hibernate的增删改查
采用JUnit测试,继承TestCase import java.util.Date; import junit.framework.TestCase; import org.hibernate.Se ...
- Hibernate学习笔记(六) — Hibernate的二级缓存
我们知道hibernate的一级缓存是将数据缓存到了session中从而降低与数据库的交互.那么二级缓存呢? 一.应用场合 比方.在12306购票时.须要选择出发地与目的地,假设每点一次都与数据库交互 ...
- Hibernate学习笔记四:事务管理
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6768298.html 一:需要事务的Session操作 Session操作中,查询类操作是不需要事务就能生效 ...
- hibernate学习笔记之一 hibernate简介
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架 hibernate可以自动生成SQL语句,自 ...
- Hibernate学习笔记(二)
2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...
- Hibernate学习笔记(一)
2016/4/18 19:58:58 Hibernate学习笔记(一) 1.Hibernate框架的概述: 就是一个持久层的ORM框架. ORM:对象关系映射.将Java中实体对象与关系型数据库中表建 ...
- Hibernate 学习笔记一
Hibernate 学习笔记一 今天学习了hibernate的一点入门知识,主要是配置domain对象和表的关系映射,hibernate的一些常用的配置,以及对应的一个向数据库插入数据的小例子.期间碰 ...
- Hibernate学习笔记-Hibernate HQL查询
Session是持久层操作的基础,相当于JDBC中的Connection,通过Session会话来保存.更新.查找数据.session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库 ...
- 多线程学习笔记九之ThreadLocal
目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...
随机推荐
- 【扩展欧几里得】Bzoj 1407: [Noi2002]Savage
Description Input 第1行为一个整数N(1<=N<=15),即野人的数目.第2行到第N+1每行为三个整数Ci, Pi, Li (1<=Ci,Pi<=100, 0 ...
- hdu 4336 Card Collector 容斥原理
读完题目就知道要使用容斥原理做! 下面用的是二进制实现的容斥原理,详见:http://www.cnblogs.com/xin-hua/p/3213050.html 代码如下: #include< ...
- Maven打包时囊括本地依赖的jar包
在开发中,偶尔会遇到一个问题:某些比较冷门的包,maven服务器上没有,而我们又必须用,通常情况下会在项目中建立一个lib文件夹.将这些包copy进去并加入buildpath,开发就可以继续了,如下图 ...
- 轻量级Java_EE企业应用实战-第5章Hibernate的基本用法-001
1. package org.crazyit.app.domain; import javax.persistence.*; /** * Description: <br/> * ��վ: ...
- FocusWriter
2. FocusWriter 如果你正在从事某种写作——小说.博客.文档等——你绝对希望认识一下FocusWriter.它已经有近十年的发布历史了,但是一直是我们最喜欢的无分心写作应用之一.如果你希望 ...
- SQLite数据类型详解
一.存储种类和数据类型: SQLite将数据值的存储划分为以下几种存储类型: 复制代码代码如下: NULL: 表示该值为NULL值. INTEGER: 无符号整型值. R ...
- ArcGIS Runtime for Android开发教程V2.0(3)基础篇---Hello World Map
原文地址: ArcGIS Runtime for Android开发教程V2.0(3)基础篇---Hello World Map - ArcGIS_Mobile的专栏 - 博客频道 - CSDN.NE ...
- 117. Populating Next Right Pointers in Each Node II
题目: Follow up for problem "Populating Next Right Pointers in Each Node". What if the given ...
- 50个非常有用的PHP工具
PHP是使用最为广泛的开源服务器端脚本语言之一,当然PHP并不是速度最快的,但它却是最常用的脚本语言.这里有50个有益的PHP工具,可以大大提高你的编程工作: 调试工具 Webgrind Xdebug ...
- poj2400Supervisor, Supervisee(KM)
http://poj.org/problem?id=2400 KM算法http://philoscience.iteye.com/blog/1754498 题意:每个雇主对雇员有个满意度 雇员对雇主有 ...