Hibernate本身没有事务的实现
Hibernate 直接使用 JDBC 连接和 JTA 资源,不添加任何附加锁定行为。也就是说你在Hibernate里面使用的事务要么是JDBC的事务,要么是JTA的事务。
Hibernate不锁定内存中的对象
你的应用程序会按照你的数据库事务的隔离级别规定的那样运作,真正对事务的实现和支持也依赖于数据库。
 
对于并发处理,Hibernate提供了乐观锁和悲观锁来进行并发处理
Hibernate对自动乐观并发控制提供版本管理,针对行级悲观锁定,Hibernate 也提供了辅助的(较小的)API,它使用了 SELECT FOR UPDATE 的 SQL 语法
Hibernate的Session是和事务联系在一起的
可以通过Session去获取事务的接口,从而进行事务的控制。
 
数据库事务应该尽可能的短
这样能降低数据库中的锁争用。数据库长事务会阻止你的应用程序扩展到高的并发负载。因此,假若在用户思考期间让数据库事务开着,直到整个工作单元完成才关闭这个事务,这绝不是一个好的设计。
这就引出一个问题:一个操作单元,也就是一个事务单元的范围应该是多大?
一个操作一个?一个请求一个?一个应用一个?
 
反模式:session-per-operation
在单个线程中, 不要因为一次简单的数据库调用,就打开和关闭一次 Session!数据库事务也是如此。也就是说应该禁止自动事务提交(auto-commit)。

session-per-request
最常用的模式是 每个请求一个会话。 在这种模式下,来自客户端的请求被发送到服务器端,即 Hibernate 持久化层运行的地方,一个新的 Hibernate Session 被打开,并且执行这个操作单元中所有的数据库操作。一旦操作完成(同时对客户端的响应也准备就绪),session 被同步,然后关闭。会话和请求之间的关系是一对一的关系。
Hibernate 内置了对“当前 session(current session)” 的管理,用于简化此模式。你要做的一切就是在服务器端要处理请求的时候,开启事务,在响应发送给客户之前结束事务,通常使用Servelt Filter来完成。

非托管环境下
所谓非托管,指的是:应用程序没有托管到J2EE环境中,通常由Hibernate自己来负责管理数据库连接池。应用程序开发人员必须手工设置事务声明,换句话说,就是手工启动,提交,或者回滚数据库事务。
 
使用JTA
又有两种方式,一种是在Hibernate配置里面修改transaction的factory类,从而在程序里面可以直接使用Hibernate的事务API,也就是程序不用变化。
另外一种方式就是直接通过JNDI去查找UserTransaction,然后直接在程序里面使用JTA的接口来控制事务。
应用程序级别的版本检查
简单点说,就是由应用程序自己实现版本检查来确保对话事务的隔离,从数据访问的角度来说是最低效的,不推荐使用。
 
扩展周期的session和自动版本化
Hibernate 使用扩展周期的 Session 的方式,或者脱管对象实例的方式来提供自动版本检查。单个 Session 实例和它所关联的所有持久化对象实例都被用于整个对话,这被称为 session-per-
conversation。
Hibernate 在同步的时候进行对象实例的版本检查,如果检测到并发修改则抛出异常。由开发人员来决定是否需要捕获和处理这个异常(通常的抉择是给用户 提供一个合并更改,或者在无脏数据情况下重新进行业务对话的机会)。
在等待用户交互的时候, Session 断开底层的 JDBC 连接。这种方式以数据库访问的角度来说是最高效的方式。应用程序不需要关心版本检查或脱管对象实例的重新关联,在每个数据库事务中,应用程序也不需要载入读取对象实例。
应用程序级别的版本检查
简单点说,就是由应用程序自己实现版本检查来确保对话事务的隔离,从数据访问的角度来说是最低效的,不推荐使用。
 
扩展周期的session和自动版本化
Hibernate 使用扩展周期的 Session 的方式,或者脱管对象实例的方式来提供自动版本检查。单个 Session 实例和它所关联的所有持久化对象实例都被用于整个对话,这被称为 sessionper-conversation。
Hibernate 在同步的时候进行对象实例的版本检查,如果检测到并发修改则抛出异常。由开发人员来决定是否需要捕获和处理这个异常(通常的抉择是给用户 提供一个合并更改,或者在无脏数据情况下重新进行业务对话的机会)。
在等待用户交互的时候, Session 断开底层的 JDBC 连接。这种方式以数据库访问的角度来说是最高效的方式。应用程序不需要关心版本检查或脱管对象实例的重新关联,在每个数据库事务中,应用程序也不需要载入读取对象实例。
通常不需要自己去管理锁定策略
Hibernate 总是使用数据库的锁定机制,从不在内存中锁定对象。因而用户并不需要花很多精力去担心锁定策略的问题。通常情况下,只要为 JDBC 连接指定一下隔离级别,然后让数据库去搞定一切就够了。
然而,高级用户有时候希望进行一个排它的悲观锁定,或者在一个新的事务启动的时候,重新进行锁定。
 
类 LockMode 定义了Hibernate 所需的不同的锁定级别
1:当更新或者插入一行记录的时候,锁定级别自动设置为LockMode.WRITE。
2:当用户显式的使用数据库支持的 SQL 格式 SELECT ... FOR UPDATE 发送 SQL 的时候,锁定级别设置为 LockMode.UPGRADE。
3:当用户显式的使用 Oracle 数据库的 SQL 语句 SELECT ... FOR UPDATE NOWAIT 的时候,锁定级别设置 LockMode.UPGRADE_NOWAIT。
4:当 Hibernate 在“可重复读”或者是“序列化”数据库隔离级别下读取数据的时候,锁定模式自动设置为 LockMode.READ。这种模式也可以通过用户显式指定进行设置。
5:LockMode.NONE 代表无需锁定。在 Transaction 结束时, 所有的对象都切换到该模式上来。与session 相关联的对象通过调用 update() 或者 saveOrUpdate() 脱离该模式。
 
显示的指定锁定模式
1:调用 Session.load() 的时候指定锁定模式(LockMode)。
2:调用 Session.lock()。
3:调用 Query.setLockMode()。
显示指定锁定模式的说明
1:如果在 UPGRADE 或者 UPGRADE_NOWAIT 锁定模式下调用 Session.load(),并且要读取的对象尚未被session 载入过,那么对象通过 SELECT ... FOR UPDATE 这样的 SQL 语句被载入。如果为一个对象调用 load() 方法时,该对象已经在另一个较少限制的锁定模式下被载入了,那么 Hibernate 就对该对象调用 lock() 方法。
2:如果指定的锁定模式是 READ,UPGRADE 或 UPGRADE_NOWAIT,那么 Session.lock() 就执行版本号检查。(在 UPGRADE 或者 UPGRADE_NOWAIT 锁定模式下,执行 SELECT ... FOR UPDATE这样的SQL语句。)
3:如果数据库不支持用户设置的锁定模式,Hibernate 将使用适当的替代模式(而不是扔出异常)。这一点可以确保应用程序的可移植性。
 

Hibernate4教程五:事务和并发的更多相关文章

  1. Spring Boot 2.x基础教程:事务管理入门

    什么是事务? 我们在开发企业应用时,通常业务人员的一个操作实际上是对数据库读写的多步操作的结合.由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻 ...

  2. CRL快速开发框架系列教程五(使用缓存)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  3. Microsoft SQL Server中的事务与并发详解

    本篇索引: 1.事务 2.锁定和阻塞 3.隔离级别 4.死锁 一.事务 1.1 事务的概念 事务是作为单个工作单元而执行的一系列操作,比如查询和修改数据等. 事务是数据库并发控制的基本单位,一条或者一 ...

  4. C#微信公众号开发系列教程五(接收事件推送与消息排重)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

  5. Hibernate事务与并发问题处理(乐观锁与悲观锁)

    目录 一.数据库事务的定义 二.数据库事务并发可能带来的问题 三.数据库事务隔离级别 四.使用Hibernate设置数据库隔离级别 五.使用悲观锁解决事务并发问题 六.使用乐观锁解决事务并发问题 Hi ...

  6. 黄聪:Microsoft Enterprise Library 5.0 系列教程(五) Data Access Application Block

    原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(五) Data Access Application Block 企业库数据库访问模块通过抽象工厂模式,允许用户 ...

  7. Quartz教程五:SimpleTrigger

    原文链接 | 译文链接 | 翻译:nkcoder 本系列教程由quartz-2.2.x官方文档翻译.整理而来,希望给同样对quartz感兴趣的朋友一些参考和帮助,有任何不当或错误之处,欢迎指正:有兴趣 ...

  8. Elasticsearch入门教程(五):Elasticsearch查询(一)

    原文:Elasticsearch入门教程(五):Elasticsearch查询(一) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...

  9. MySQL事务与并发

      很多程序员都学过MySQL,而且也会写SQL语句.但仅仅会写还远远不够,在面试中以及在工作中,还必须要会事务和并发. 一.事务 事务是满足 ACID 特性的操作,可以通过 Commit 提交事务, ...

随机推荐

  1. 环境管理 pipenv 的 使用

    安装 pip3 install pipenv 配置 配置 环境变量 WORKON_HOME , 表示 生成的虚拟环境 文件 的 存放位置 创建虚拟环境 方式一 pipenv --python 3.7 ...

  2. python常用函数 H

    heapify(iterable) 堆排序. 例子: heappop(iterable) 弹出堆排序的第一个元素,即最小值. 例子: hasattr(object,attr) 用于确定对象是否有某个属 ...

  3. Vue:子组件如何跟父组件通信

    我们知道,父组件使用 prop 传递数据给子组件.但子组件怎么跟父组件通信呢?这个时候 Vue 的自定义事件系统就派得上用场了. 使用 v-on 绑定自定义事件 每个 Vue 实例都实现了事件接口,即 ...

  4. java23种设计模式(五)--组合模式

    转载:https://www.cnblogs.com/V1haoge/p/6489827.html定义:所谓组合模式,其实说的是对象包含对象的问题,通过组合的方式(在对象内部引用对象)来进行布局,我认 ...

  5. BZOJ2213 & LOJ2161 「POI2011 R2 Day1」Difference 最大子段和

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2213 https://loj.ac/problem/2161 题解 做一道简单题来放松一下. ...

  6. 分布式架构的CAP原理

    CAP 定理的含义   一.分布式系统的三个指标 1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标. Consistency Availability Parti ...

  7. windows下zookeeper单机版安装+dubbo-admin安装注意点

    一:zookeeper安装 安转包下载地址:http://www.apache.org/dyn/closer.cgi/zookeeper 复制修改conf下的zoo_sample.cfg为zoo.cf ...

  8. less和vim中使用正则表达式搜索

    使用less查看 txt 文件之后,按\可以正则表达式来搜索: less phonelist.txt (232) 298-2265 (624) 381-1078 (540) 126-1980 (874 ...

  9. find命令查找目录

    find <path> -type d -name "dir_name" -type d是查找目录的参数,如果是查找其他的: -type b: Block specia ...

  10. mybatis源码分析之05一级缓存

    首先需要明白,mybatis的一级缓存就是指SqlSession缓存,Map缓存! 通过前面的源码分析知道mybatis框架默认使用的是DefaultSqlSession,它是由DefaultSqlS ...