java

位置:IT落伍者 >> java >> 浏览文章

分析Hibernate的事务处理机制


发布日期:2021年10月03日
 
分析Hibernate的事务处理机制

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

上一篇:jboss下配置虚拟主机

下一篇:Hibernate 命名查询NamedQuery