分析Hibernate的事务处理机制
Hibernate是对JDBC的轻量级对象封装,Hibernate本身是不具备Transaction处理功能的,Hibernate的 Transaction实际上是底层的JDBC Transaction的封装,或者是JTA Transaction的封装,下面我们详细的分析:
Hibernate可以配置为JDBCTransaction或者是JTATransaction,这取决于你在hibernate.properties中的配置:
| #hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory #hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory |
如果你什么都不配置,默认情况下使用JDBCTransaction,如果你配置为:
| hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory |
将使用JTATransaction,不管你准备让Hibernate使用JDBCTransaction,还是JTATransaction,我的忠告就是什么都不配,将让它保持默认状态,如下:
| #hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory #hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory |
在下面的分析中我会给出原因。
一、JDBC Transaction
看看使用JDBC Transaction的时候我们的代码例子:
| Session session = sf.openSession(); Transaction tx = session.beginTransactioin(); ... session.flush(); tx.commit(); session.close(); |
这是默认的情况,当你在代码中使用Hibernate的Transaction的时候实际上就是JDBCTransaction。那么JDBCTransaction究竟是什么东西呢?来看看源代码就清楚了:
Hibernate2.0.3源代码中的类
net.sf.hibernate.transaction.JDBCTransaction:
| public void begin() throws HibernateException { ... if (toggleAutoCommit) session.connection().setAutoCommit(false); ... } |
这是启动Transaction的方法,看到 connection().setAutoCommit(false) 了吗?是不是很熟悉?
再来看
| public void commit() throws HibernateException { ... try { if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush(); try { session.connection().commit(); committed = true; } ... toggleAutoCommit(); } |
这是提交方法,看到connection().commit()
了吗?下面就不用我多说了,这个类代码非常简单易懂,通过阅读使我们明白Hibernate的Transaction都在干了些什么?我现在把用
Hibernate写的例子翻译成JDBC,大家就一目了然了:
| Connection conn = ...; <--- session = sf.openSession(); conn.setAutoCommit(false); <--- tx = session.beginTransactioin(); ... <--- ... conn.commit(); <--- tx.commit(); (对应左边的两句) conn.setAutoCommit(true); conn.close(); <--- session.close(); |
看明白了吧,Hibernate的JDBCTransaction根本就是conn.commit而已,根本毫无神秘可言,只不过在Hibernate
中,Session打开的时候,就会自动conn.setAutoCommit(false),不像一般的JDBC,默认都是true,所以你最后不写
commit也没有关系,由于Hibernate已经把AutoCommit给关掉了,所以用Hibernate的时候,你在程序中不写
Transaction的话,数据库根本就没有反应。
二、JTATransaction
如果你在EJB中使用Hibernate,或者准备用JTA来管理跨Session的长事务,那么就需要使用JTATransaction,先看一个例子:
| javax.transaction.UserTransaction tx = new InitialContext().lookup("javax.transaction.UserTransaction"); Session s1 = sf.openSession(); ... s1.flush(); s1.close(); ... Session s2 = sf.openSession(); ... s2.flush(); s2.close(); tx.commit(); |
这是标准的使用JTA的代码片断,Transaction是跨Session的,它的生命周期比Session要长。如果你在EJB中使用
Hibernate,那么是最简单不过的了,你什么Transaction代码统统都不要写了,直接在EJB的部署描述符上配置某某方法是否使用事务就可
以了。
现在我们来分析一下JTATransaction的源代码, net.sf.hibernate.transaction.JTATransaction:
| public void begin(InitialContext context, ... ... ut = (UserTransaction) context.lookup(utName); ... |
看清楚了吗? 和我上面写的代码 tx = new Initial Context?().lookup("javax.transaction.UserTransaction"); 是不是完全一样?
| public void commit() ... ... if (newTransaction) ut.commit(); ... |
JTATransaction的控制稍微复杂,不过仍然可以很清楚的看出来Hibernate是如何封装JTA的Transaction代码的。
但是你现在是否看到了什么问题? 仔细想一下,Hibernate Transaction是从Session中获得的,tx =
session.beginTransaction(),最后要先提交tx,然后再session.close,这完全符合JDBC的
Transaction的操作顺序,但是这个顺序是和JTA的Transactioin操作顺序彻底矛盾的!!!
JTA是先启动Transaction,然后启动Session,关闭Session,最后提交Transaction,因此当你使用JTA的
Transaction的时候,那么就千万不要使用Hibernate的Transaction,而是应该像我上面的JTA的代码片断那样使用才行。
总结:
1、在JDBC上使用Hibernate 必须写上Hibernate Transaction代码,否则数据库没有反应。此时Hibernate的Transaction就是Connection.commit而已
2、在JTA上使用Hibernate 写JTA的Transaction代码,不要写Hibernate的Transaction代码,否则程序会报错
3、在EJB上使用Hibernate 什么Transactioin代码都不要写,在EJB的部署描述符里面配置
|---CMT(Container Managed Transaction)
|
|---BMT(Bean Managed Transaction)
|
|----JDBC Transaction
|
|----JTA Transaction
鸣谢:http://www.yesky.com/255/1922255.shtml
分析Hibernate的事务处理机制的更多相关文章
- Hibernate的事务处理机制和flush方法的用法
关于在使用hibernate在提交事务时常遇到的异常: an assertion failure occured (this may indicate a bug in Hibernate, but ...
- Hibernate笔记——缓存机制详细分析
原文:http://www.cnblogs.com/xiaoluo501395377/p/3377604.html ========================================== ...
- atitit.spring hibernate的事务机制 spring不能保存对象的解决
atitit.spring hibernate的事务机制 spring不能保存对象的解决 sessionFactory.openSession() 不能..log黑头马sql语言.. sessionF ...
- 从一次异常中浅谈Hibernate的flush机制
摘自http://www.niwozhi.net/demo_c70_i1482.html http://blog.itpub.net/1586/viewspace-829613/ 这是在一次事务提交时 ...
- Android架构分析之Android消息处理机制(二)
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本号:4.4.2 在上一篇文章中我们看了一个使用Handler处理Message消息的样例,本文我们 ...
- Solr4.8.0源码分析(19)之缓存机制(二)
Solr4.8.0源码分析(19)之缓存机制(二) 前文<Solr4.8.0源码分析(18)之缓存机制(一)>介绍了Solr缓存的生命周期,重点介绍了Solr缓存的warn过程.本节将更深 ...
- Solr4.8.0源码分析(18)之缓存机制(一)
Solr4.8.0源码分析(18)之缓存机制(一) 前文在介绍commit的时候具体介绍了getSearcher()的实现,并提到了Solr的预热warn.那么本文开始将详细来学习下Solr的缓存机制 ...
- J2EE进阶(八)Hibernate与延迟加载机制探究
Hibernate与延迟加载机制探究 前言 Hibernate对象关系映射提供延迟的与非延迟的对象初始化.非延迟加载在读取一个对象的时候会将与这个对象所有相关的其他对象一起读取出来.这有时会导致成百的 ...
- 【JVM】深度分析Java的ClassLoader机制(源码级别)
原文:深度分析Java的ClassLoader机制(源码级别) 为了更好的理解类的加载机制,我们来深入研究一下ClassLoader和他的loadClass()方法. 源码分析 public abst ...
随机推荐
- 7月15日学习之BOM
setTimeout() //延时器,只执行一次代码 clearTimeout() //清除演示器 setIntervla() //定时器,根据指定时间间隔执行一次代码 clearInterval() ...
- Debian8 加载NTFS 磁盘出错 解决方法
执行 ntfsfix /dev/sdb2 // sd* a代表第一块硬盘 b代表第2块硬盘 数字是分区号 执行后 就可以正常使用了.
- 解决TextView在显示文字的时候,一行还没显示满就跳到下一行
转载请注明:转自 http://blog.csdn.NET/u011176685/article/details/48295185 一.问题描述: Android的TextView在显示文字的时候,如 ...
- 制作BibTex文件
上一篇日志中讲到了在LaTeX中使用BibTex管理参考文献,这篇日志具体总结下如何制作BibTex文件. 制作BibTex文件,主要有以下几种方法: 手工制作: 直接从期刊数据库中下载: 借助Goo ...
- 解释清楚c++的重载操作符【用自己的话,解释清楚】
C++中对于内置的变量及标准库中常见的类定义类常见的操作符含义,对于自定义的类也可以通过关键字operate 重载操作符的含义. C++中支持重载的目的 诚然操作符的重载可以通过使用函数实现同样的功能 ...
- vJine 第三波 之 Lua 来袭 vJine.Lua
vJine.Lua vJine.Lua是Lua语言的C#封装库,可实现通过C#直接运行Lua脚本并与Lua脚本交互的功能. 1. 授权: MPL2.0 相关资源: nuget:(https://www ...
- c#中设置像数量,价格,金额等的textbox的限制条件,用户只能输入数字或小数
#region 设置数量等textbox控件样式及限制条件(具体调用的方法就是重写或直接调用ShieldNumberTextBoxOtherKeys函数) /// <summary> // ...
- echarts标准饼图解读(一)——提示框(tooltip)配置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- mysql配置优化测试
http://bjlfp.blog.163.com/blog/static/77368461201211695924524/ 感觉真不错啊.观察几天看看
- Android SDK Manager国内无法更新的解决方案
万里长城永不倒,千里黄河水滔滔.算了跑题了. 但还是要吐槽这下这个万里长城,感谢 方滨兴 叫兽 给我们净化了互联网,靠!什么&!@#¥ 此处略去一万字. 现在由于GWF,google基本和咱们 ...