Hibernate是对JDBC的轻量级对象封装Hibernate本身是不具备Transaction处理功能的Hibernate的Transaction实际上是底层的JDBC Transaction的封装或者是JTA Transaction的封装下面我们详细的分析
Hibernate可以配置为JDBCTransaction或者是JTATransaction这取决于你在hibernateproperties中的配置:
#hibernatetransactionfactory_class
netsfhibernatetransactionJTATransactionFactory
#hibernatetransactionfactory_class
netsfhibernatetransactionJDBCTransactionFactory
如果你什么都不配置默认情况下使用JDBCTransaction如果你配置为
hibernatetransactionfactory_class
netsfhibernatetransactionJTATransactionFactory
将使用JTATransaction不管你准备让Hibernate使用JDBCTransaction还是JTATransaction我的忠告就是什么都不配将让它保持默认状态如下
#hibernatetransactionfactory_class
netsfhibernatetransactionJTATransactionFactory
#hibernatetransactionfactory_class
netsfhibernatetransactionJDBCTransactionFactory
在下面的分析中我会给出原因
一JDBC Transaction
看看使用JDBC Transaction的时候我们的代码例子
Session session = sfopenSession();
Transaction tx = sessionbeginTransactioin();
sessionflush();
mit();
sessionclose();
这是默认的情况当你在代码中使用Hibernate的Transaction的时候实际上就是JDBCTransaction那么JDBCTransaction究竟是什么东西呢?来看看源代码就清楚了
Hibernate源代码中的类
netsfhibernatetransactionJDBCTransaction:
public void begin() throws HibernateException {
if (toggleAutoCommit) nnection()setAutoCommit(false);
}
这是启动Transaction的方法看到 connection()setAutoCommit(false) 了吗?是不是很熟悉?
再来看
public void commit() throws HibernateException {
try {
if ( sessiongetFlushMode()!=FlushModeNEVER ) sessionflush();
try {
nnection(mit();
committed = true;
}
toggleAutoCommit();
}
这是提交方法看到connection(mit() 了吗?下面就不用我多说了这个类代码非常简单易懂通过阅读使我们明白Hibernate的Transaction都在干了些什么?我现在把用Hibernate写的例子翻译成JDBC大家就一目了然了
Connection conn = ; < session = sfopenSession();
connsetAutoCommit(false); < tx = sessionbeginTransactioin();
<
mit(); < mit(); (对应左边的两句)
connsetAutoCommit(true);
connclose(); < sessionclose();
看明白了吧Hibernate的JDBCTransaction根本就是mit而已根本毫无神秘可言只不过在Hibernate中Session打开的时候就会自动connsetAutoCommit(false)不像一般的JDBC默认都是true所以你最后不写commit也没有关系由于Hibernate已经把AutoCommit给关掉了所以用Hibernate的时候你在程序中不写Transaction的话数据库根本就没有反应
二JTATransaction
如果你在EJB中使用Hibernate或者准备用JTA来管理跨Session的长事务那么就需要使用JTATransaction先看一个例子
javaxtransactionUserTransaction tx = new
InitialContext()lookup(javaxtransactionUserTransaction);
Session s = sfopenSession();
sflush();
sclose();
Session s = sfopenSession();
sflush();
sclose();
mit();
这是标准的使用JTA的代码片断Transaction是跨Session的它的生命周期比Session要长如果你在EJB中使用Hibernate那么是最简单不过的了你什么Transaction代码统统都不要写了直接在EJB的部署描述符上配置某某方法是否使用事务就可以了
现在我们来分析一下JTATransaction的源代码 netsfhibernatetransactionJTATransaction:
public void begin(InitialContext context
ut = (UserTransaction) contextlookup(utName);
看清楚了吗? 和我上面写的代码 tx = new Initial Context?()lookup(javaxtransactionUserTransaction); 是不是完全一样?
public void commit()
if (newTransaction) mit();
JTATransaction的控制稍微复杂不过仍然可以很清楚的看出来Hibernate是如何封装JTA的Transaction代码的
但是你现在是否看到了什么问题? 仔细想一下Hibernate Transaction是从Session中获得的tx = sessionbeginTransaction()最后要先提交tx然后再sessionclose这完全符合JDBC的Transaction的操作顺序但是这个顺序是和JTA的Transactioin操作顺序彻底矛盾的!!! JTA是先启动Transaction然后启动Session关闭Session最后提交Transaction因此当你使用JTA的Transaction的时候那么就千万不要使用Hibernate的Transaction而是应该像我上面的JTA的代码片断那样使用才行
总结
在JDBC上使用Hibernate 必须写上Hibernate Transaction代码否则数据库没有反应此时Hibernate的Transaction就是mit而已
在JTA上使用Hibernate 写JTA的Transaction代码不要写Hibernate的Transaction代码否则程序会报错
在EJB上使用Hibernate 什么Transactioin代码都不要写在EJB的部署描述符里面配置
|CMT(Container Managed Transaction)
|
|BMT(Bean Managed Transaction)
|
|JDBC Transaction
|
|JTA Transaction