分析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 ...
随机推荐
- [转]C#如何在ListView失去焦点的情况下仍然保持Item高亮
private void listView1_SelectedIndexChanged(object sender, EventArgs e) { foreach(ListViewItem itm i ...
- 160多个android开源代码汇总
第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.Pro ...
- 随笔001:Group by 语法剪辑
基本语法: GROUP BY [ALL] group_by_expression[,……n][WITH (CUBE|ROLLUP)] 参数说明: ALL:用于指定包含所有组和结果集,甚至包含那些其中任 ...
- CentOS 关闭蜂鸣
临时:sudo rmmod pcspkr 永久 /etc/inputrc文件中把 set bell-style none 前的注释去掉,改为 set bell-style off 转自:http:// ...
- VS2013 打开项目时出现 未定义标识符string的解决办法
---恢复内容开始--- 前两天从前辈那儿弄到一份源码,VC 6时期写出来的mfc程序. 打开之后直接编译编译成功,可以运行.但是看代码的时候却发现出现了好多错误,如 未定义标识符string,NUL ...
- mysql5.7版本免安装配置教程
自己花了两天时间才搞清楚,希望对新手有一定帮助,有问题可以联系哦! mysql分为安装版本msi,免安装要压缩版本ZIP,下载网址:http://dev.mysql.com/downloads 免安装 ...
- Apache 安装与配置
安装Apache 1.下载apache软件http://www.apache.org 2.安装 以管理员身份进行安装 3.设置主机名与域名 4.选择安装类型 5.自定义安装路径 6.开始安装 7.安装 ...
- hibernate的id生成策略
欢迎转载,请注明出处http://www.cnblogs.com/shizhongtao/p/3436523.html 一.xml配置方式的id生成 <id name="id" ...
- ThinkPHP3.2 加载过程(二)
回顾: 上次介绍了 ThinkPHP 的 Index.PHP入口文件.但只是TP的入口前面的入口(刷boss总是要过好几关才能让你看到 ,不然boss都没面子啊),从Index.PHP最后一行把我们引 ...
- 【Sqlserver】修改数据库表中的数据:对缺失的数据根据已有的数据进行修补
1 --查询时间范围内的数据 select * from dbo.point where wtime >'2014-05-01 23:59:59' and wtime< '2014-05- ...