Hibernate是对JDBC的轻量级对象封装,Hibernate本身是不具备Transaction处理功能的,Hibernate的 Transaction实际上是底层的JDBC Transaction的封装,或者是JTA Transaction的封装. 默认情况下使用的是JDBCTransaction.
hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory
最好是什么都不配,让Hibernate采用默认的事务处理机制.而且真正的事务处理要放到业务层来做.
1. JDBC Transaction
看看使用JDBC Transaction的时候我们的代码例子:
Session session = sf.openSession();
Transaction tx = session.beginTransactioin();
...
session.flush();
tx.commit();
session.close();
这是默认的情况,当你在代码中使用Hibernate的Transaction的时候实际上就是JDBCTransaction。那么JDBCTransaction究竟是什么东西呢?来看看源代码就清楚了:
public class JDBCTransaction implements Transaction
public void begin() throws HibernateException {
...
if (toggleAutoCommit) jdbcContext.connection().setAutoCommit(false);
...
}
这是启动Transaction的方法,再来看提交方法:
public void commit() throws HibernateException {
...
jdbcContext.connection().commit();
...
jdbcContext.connection().setAutoCommit( true );
...
}
我现在把用 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的时候,你在程序中不写 Transaction的话,数据库根本就没有反应。
2.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要长。
但是你现在是否看到了什么问题? 仔细想一下,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代码,否则程序会报错.