分析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 ...
随机推荐
- asp.net自定义控件
回发星级控件 using System; using System.ComponentModel; using System.Web.UI; using System.Web.UI.WebContro ...
- Ajax-数据格式-xml,json
xml demo testDataXml <%@ page language="java" contentType="text/html; charset=UTF- ...
- mvc中的webapi
MVC中 webapi的使用 和 在其他网站中如何来调用(MVC) 1.webapi的路由规则注册在App_Start\WebApiConfig.cs文件中 2.webapi控制器继承父类 apiCo ...
- CSS之显示天气
这个可以有,自从有了这个,以后查询天气就方便多了,哈哈. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...
- GPU总结(1)
目录 1.为什么要引入GPU 2.CUDA环境的搭建--CUDA全称Compute Unified Device Architecture统一计算设备架构,CUDA是以后总将GPU作为数据并行计算设备 ...
- XCode中的特殊快捷键图标
⌘——Command () ⌃ ——Control ⌥——Option (alt) ⇧——Shift ⇪——Caps Lock fn——功能键就是fn
- C#对象XML序列化
1.Xml序列化操作类 .Net Framework提供了对应的System.Xml.Seriazliation.XmlSerializer负责把对象序列化到XML,和从XML中反序列化为对象. 以下 ...
- 1.6建造者模式(生成器模式) Builder
1.概念:将一个复杂对象的构建和他的表示分离,使得同样的构件可以创建不同的表示. 2.实例:肯德基和中餐,肯德基抽象了整个做菜的复杂过程(相同的构建),然后在不同的店铺进行实现(不同的表示).中餐往往 ...
- [转]重叠IO
本章回答了如下几个问题: ◆ 什么是Overlapped I/O?为什么需要Overlapped I/O?如何让数据传输支持Overlapped I/O? ◆ 数据传输结束后,Win32提供了哪些方式 ...
- 使用thinkPHP框架实现删除和批量删除一例【原创】
本文为作者原创,转载请注明原作者及转载地址. 上一篇讲了如何用thinkPHP框架实现数据的添加,那这一篇就讲一下如何用thinkPHP实现数据的删除和批量删除吧. 预期效果图: 原谅博主对照片的处理 ...