• 分析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

  • 相关阅读:
    nullnullConnecting with WiFi Direct 与WiFi直接连接
    nullnullUsing WiFi Direct for Service Discovery 直接使用WiFi服务发现
    nullnullSetting Up the Loader 设置装载机
    nullnullDefining and Launching the Query 定义和启动查询
    nullnullHandling the Results 处理结果
    装置输出喷泉装置(贪心问题)
    数据状态什么是事务?
    停止方法iOS CGD 任务开始与结束
    盘文件云存储——金山快盘
    函数标识符解决jQuery与其他库冲突的方法
  • 原文地址:https://www.cnblogs.com/wql025/p/4822787.html
Copyright © 2020-2023  润新知