Hibernate 之 Locking
在我们业务实现的过程中,往往会有这样的需求:保证数据访问的排他性,也就是我正在访问的数据,别人不能够访问,或者不能对我的数据进行操作.面对这样的需求,就需要通过一种机制来保证这些数据在一定的操作过程中不会被他人修改,这种机制就是我们今天要说的Locking 即"锁".由此我们可以得出一个小结论,锁主要是解决并发性问题.
Hibernate支持两种锁机制:"悲观锁"(Pessimistic
Locking )和"乐观锁"(Optimistic
Locking )
先来看悲观锁
通过悲观这两个字我们能够看出,它对数据被外界操作所采取的态度是悲观的,保守的.也就是在整个数据处理的过程中,,它都将数据处于锁定状态.悲观锁,通常是由数据库机制实现的,在整个过程中把数据锁住(查询时),只要事务不释放(提交/回滚)那么任何用户都不能查看或修改.需要等待资源释放.
接下来将通过一个简单查询语句来解释Hibernate是如何实现悲观锁.
- //查询用户为"jnqqls"的用户
- String hqlStr ="from User as user where user.name='Jnqqls'";
- Query query = session.createQuery(hqlStr);
- // 加锁
- query.setLockMode("user",LockMode.UPGRADE);
- // 执行查询,获取数据
- List userList = query.list();
通过查看运行时Hibernate的执行语句会发现,它是通过数据库的for update子句来实现了悲观锁的机制.
根据悲观锁的保守特点,在并发比较高的情况下不建议使用.特别是事务内的执行周期特别的长的情况下,其他请求资源都处于等待状态,导致数据库性能的大量开销.
接下来来看乐观锁
乐观锁(其实根本上不是锁,跟数据库没有关系.而是解决冲突的检测手段,机制是在数据库中加字段,例如增加一个版本号或者是时间戳).
Hibernate实现乐观锁机制的原理
大多数的使用是采用数据版本的方式(version)实现,一般在数据库中加入一个version字段在读取数据的时候将version读取出来,在保存数据的时候判断version的值是否小于数据库中的version值,如果小于不予更新,否则给予更新.
了解原理之后接下来我们将会通过代码来了解Hibernate是如何实现乐观锁.
第一步,在Hibernate配置文件中添加version字段,Hibernate会自动进行相关的锁处理.
- <?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>
- <class name="com.tgb.hibernate.User" table="t_user" optimistic-lock="version">
- <id name="id">
- <generator class="assigned"/>
- </id>
- <version name="version"/>
- <property name="name"/>
- <property name="age"/>
- </class>
- </hibernate-mapping>
在此配置的过程中需要注意version的结点必须在id结点之后.此处version的作用注意是存放着用户的版本信息.
下面编写一段代码,将用户的年龄减少2岁.
- public void testLoad() {
- Session session = null;
- try {
- //一个获取session的工具.
- session = HibernateUtils.getSession();
- //开启事务
- session.beginTransaction();
- //加载用户id为1001
- User User = (User)session.load(User.class, "1001");
- //打印相关信息
- System.out.println("opt1-->Id=" + user.getId());
- System.out.println("opt1-->Name=" + user.getName());
- System.out.println("opt1-->Version=" + user.getVersion());
- System.out.println("opt1-->Age=" + user.getAge());
- user.setAge(user.getAge() - 2);
- //提交事务
- session.getTransaction().commit();
- }catch(Exception e) {
- e.printStackTrace();
- session.getTransaction().rollback();
- }finally {
- //关闭session
- HibernateUtils.closeSession(session);
- }
- }
通过操作可以发现,在每次更新User信息的时候,数据库中的version字段都在递增,如果我们在session提交之前开启另外一个session2对User年龄进行操作的话会出现错误提示.
org.hibernate.StaleObjectStateException:Row was updated ordeleted by another transaction(or
unsaved-value mapping was incorrect):…………..
我们可以进行异常捕获版本错误并对用户进行相应的提示,例如"数据已经被修改".
Hibernate 锁小结
悲观锁容易出现资源等待现象,因为对资源的完整占有.如果并发逻辑的时间过长的话则会导致系统其他并发逻辑的等待,会大大降低系统的并发性,并加大数据库的开销.
乐观锁因为采用版本机制,不会出现资源等待的现象,它会在提交数据的那一瞬间去判断版本的大小,如果出现并发修改的情况则会抛出异常错误,对于乐观锁而言,异常捕获显得尤为重要.
Hibernate 之 Locking的更多相关文章
- Hibernate 中的锁( locking )
业务逻辑的实现过程中,往往需要保证数据访问的排他性.如在金融系统的日终结算处理中,我们希望针对某个 cut-off 时间点的数据进行处理,而不希望在结算进行过程中(可能是几秒种,也可能是几个小时),数 ...
- Hibernate 乐观锁(Optimistic Locking)
1.hibernate基于数据版本(Version)记录机制实现.为数据增加一个版本标识,一般是通过为数据库表增加一个"version"字段来实现. 读取出数据时,将此版本号一同读 ...
- Hibernate 悲观锁(Pessimistic Locking)
在日常开发中并发应该是比较常遇到的业务场景,Hibernate给我们提供了并发操作,接下来简单介绍一下Hibernate悲观控制. 悲观锁:用户其实并不需要花很多精力去担心锁定策略的问题,通常情况下, ...
- Hibernate中的锁机制
锁机制:是数据库为了保证数据的一致性<一个事务的各种操作不相互影响>而使各种共享资源在被并发访问访问变得有序所设计的一种规则,用来保证在当前用户进行操作数据的时候其他的用户不能对同一数据进 ...
- Hibernate.lock()方法中各种锁的区别
悲观锁 它指的是对数据被外界修改持保守态度.假定任何时刻存取数据时,都可能有另一个客户也正在存取同一笔数据,为了保持数据被操作的一致性,于是对数据采取了数据库层次的锁定状态,依靠数据库提供的锁机制来实 ...
- [转]Hibernate不能自动建表解决办法及Hibernate不同数据库的连接及SQL方言
最近开始学Hibernate,看的是李刚的那本<轻量级java ee企业应用实战>.头一个hibernate程序,我原原本本的按照书上例子写下来,同时只是改动了些mysql的连接参数,并且 ...
- JavaPersistenceWithHibernate第二版笔记Getting started with ORM-001用JPA和Hibernate实现HellowWorld(JTA、Bitronix)
一.结构 二.model层 1. package org.jpwh.model.helloworld; import javax.persistence.Entity; import javax.pe ...
- hibernate注解(转)
一.实体Bean 每个持久化POJO类都是一个实体Bean, 通过在类的定义中使用 @Entity 注解来进行声明. 声明实体Bean @Entity public class Flight impl ...
- HIbernate学习笔记(八) hibernate缓存机制
hibernate缓存 一. Session级缓存(一级缓存) 一级缓存很短和session的生命周期一致,因此也叫session级缓存或事务级缓存 hibernate一级缓存 那些方法支持一级缓存: ...
随机推荐
- 如何用 CSS 创作一个立体滑动 toggle 交互控件
效果预览 在线演示 按下右侧的"点击预览"按钮在当前页面预览,点击链接全屏预览. https://codepen.io/zhang-ou/pen/zjoOgX 可交互视频教程 此视 ...
- C语言程序内存分布
一个进程的数据在内存中的布局如下图: bss段(bss segment):可读可写不可执行,通常用来存放程序中未初始化的全局变量.bss是英文Block Started by Symbol的简称.b ...
- matlab自定义函数的五种表示(前2种重点)
1.命令文件/函数文件+函数文件:多个M文件 2.函数文件+子函数:一个M文件 3. inline:无需M文件 4.符号表达式+subs方式:无需M文件 5.字符串+subs方式:无需M文件 第一种: ...
- Python处理PDF-通过关键词定位-截取PDF中的图表
起因: 因为个人原因, 这些天了解了一下Python处理PDF的方法. 首先是PDF转txt, 这个方法比较多, 这里就不再赘述, 主要聊一下PDF中的图片获取. 这里用我自己的例子, 不过具体情况还 ...
- static静态方法的优缺点
static可以修饰成员变量,成员方法,代码块,类特点: static修饰的方法和变量,为类所属方法和变量,不会在对象销毁时销毁,所以生命周期较长.被static修饰的内容会随着类的加载而加载,优先于 ...
- NYOJ 237 游戏高手的烦恼
游戏高手的烦恼时间限制:1000 ms | 内存限制:65535 KB难度:5描述有一位传说级游戏高手,在闲暇时间里玩起了一个小游戏,游戏中,一个n*n的方块形区域里有许多敌人,玩家可以使用炸弹炸掉某 ...
- 服务器架构及实战(架构篇)- PHP建站
概述 详解 PHP的环境搭建 PHP的帮助使用和配置文件 PHP的Hello World PHP的库函数调用 PHP的Web程序 PHP的函数和面向对象使用 PHP的数据库访问 Nginx安装和配置访 ...
- NYOJ-517-最小公倍数,大数啊~~~
最小公倍数 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 为什么1小时有60分钟,而不是100分钟呢?这是历史上的习惯导致.但也并非纯粹的偶然:60是个优秀的数字,它的 ...
- Oracle臨時表空間過大問題解決
查詢資料庫伺服器時,發現資料庫伺服器磁片使用空間達到了98%,分析總共的資料檔案也不可能達到如此大,經過查詢發現原來臨時表空間的使用方式達到了 32G,導致磁碟空間使用緊張.搜索了相應的文檔與資料後, ...
- php 以单下划线或双下划线开头的命名
有2个下划线的是魔术方法,如:__construct.__destruct等等.有1个下划线的一般是私有方法,如 _initialize. 小测试: public function _test(){ ...