非托管环境下用Tyrex集成Hibernate和jdbc实现JTA事务

来源:互联网 发布:淘宝联盟怎么搜索店铺 编辑:程序博客网 时间:2024/05/22 01:59

非托管环境下用Tyrex集成Hibernate和jdbc实现JTA事务

最近在把Hibernate整合进公司产品中,公司产品使用tyrex提供JTA事务支持,自己基于JDBC实现了一套O/R Mapping,并且嵌入了tomcat,所以事务这部分是自己实现的,与tomcat的环境无关,为非托管环境下的jta,和spring对jotm的集成类似。正常的用jdbc写法如下:

boolean transaction = false;
Connection = connection = null;
try {
    transaction = TransactionUtil.begin();
    connection = ConnectionFactory.getConnection("localoracle");
    //此处执行jdbc操作
} catch (Exception e) {
    TransactionUtil.rollback();
} finally {
    if (connection != null) {
        connection.close();
    }
    TransactionUtil.commit(transaction);
}

为了集成hibernate自己实现了一个ConnectionProvider:

package com.company.bpms.client.hibernate;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.connection.ConnectionProvider;
import com.company.entity.ConnectionFactory;
import com.company.entity.GenericEntityException;
import com.company.util.Debug;

public class BPConnectionProvider implements ConnectionProvider {
    private String helperName = null;
    private static final String module = BPConnectionProvider.class.getName();

    public String getHelperName() {
        return helperName;
    }

    public void setHelperName(String helperName) {
        this.helperName = helperName;
    }

    public void configure(Properties properties) throws HibernateException {
        if (helperName == null) {
            helperName = (String)properties.get("bpms.helperName");
        }
        if (helperName == null) {
            throw new HibernateException("helperName not configured.");
        }
        Debug.logInfo("bpms.helperName: " + helperName, module);
    }

    public Connection getConnection() throws SQLException {
        try {
            return ConnectionFactory.getConnection(helperName);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            throw new SQLException(e.getMessage());
        }
    }

    public void closeConnection(Connection connection) throws SQLException {
        connection.close();
    }

    public boolean supportsAggressiveRelease() {
        return false;
    }

    public void close() throws HibernateException {
    }
}

还有一个hibernate.transaction.manager_lookup_class类:

package com.company.bpms.client.hibernate;

import java.util.Properties;
import javax.transaction.TransactionManager;
import org.hibernate.HibernateException;
import org.hibernate.transaction.TransactionManagerLookup;
import com.company.entity.TransactionFactory;

public class TyrexTransactionManagerLookup implements TransactionManagerLookup {
    public TransactionManager getTransactionManager(Properties arg0) throws HibernateException {
        TransactionManager manager = TransactionFactory.getTransactionManager();
        if (manager == null) {
            throw new HibernateException("Could not obtain Tyrex transaction manager instance");
        }
        return manager;
    }

    public String getUserTransactionName() {
        return null;
    }
}

一个Hibernate帮助类:

package com.company.bpms.client.hibernate;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.company.util.Debug;

public class HibernateUtil {
    private static SessionFactory sessionFactory;
    private static final String module = HibernateUtil.class.getName();

    public static SessionFactory getSessionFactory() throws Exception {
        if (sessionFactory == null) {
            synchronized (HibernateUtil.class) {
                if (sessionFactory == null) {
                    try {
                        sessionFactory = new Configuration().configure().buildSessionFactory();
                    } catch (Exception e) {
                        Debug.logError(e, module);
                        throw e;
                    }
                }
            }
        }
        return sessionFactory;
    }
}

配置文件:

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.provider_class"> com.company.bpms.client.hibernate.BPConnectionProvider </property>
        <property name="bpms.helperName">localoracle</property>
        <property name="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
        <property name="hibernate.transaction.manager_lookup_class"> com.company.bpms.client.hibernate.TyrexTransactionManagerLookup </property>

        <!--
            <property name="hibernate.hbm2ddl.auto">create</property>
        -->
        <mapping resource="test/entity/User.hbm.xml" />
        <mapping resource="test/entity/UserProfile.hbm.xml" />
    </session-factory>
</hibernate-configuration>

示例代码:

boolean transaction = false;
org.hibernate.Session session1 = null;
org.hibernate.Session session2 = null;
try {
    transaction = TransactionUtil.begin();
    session1 = HibernateUtil.getSessionFactory().getCurrentSession();
    //session1 = HibernateUtil.getSessionFactory().openSession();
    User user = new User();
    user.setUsername("aaa");
    session1.save(user);
    session1.flush();
    //session1.close();
    BugTypeOperate.createBugType(UtilMisc.toMap("bugtypeId", user.getUserId(), "bugtypeName", "bbb"));
    session2 = HibernateUtil.getSessionFactory().getCurrentSession();
    //session2 = HibernateUtil.getSessionFactory().openSession();
    UserProfile profile = new UserProfile();
    profile.setUserId(user.getUserId());
    profile.setCompanyAddress("aaaaaaa");
    session2.save(profile);
    session2.flush();
    //session2.close();
    out.print("OK");
} catch (Exception e) {
    Debug.logError(e);
    out.print("Error");
    TransactionUtil.rollback();
} finally {
    /*    
    if (session1 != null && session1.isOpen()) {
        Debug.logInfo("-------->colse session1");    
        session1.close();
        Debug.logInfo("--------> finish close session1");    
    }
 
    if (session2 != null && session2.isOpen()) {    
        Debug.logInfo("-------->colse session2");    
        session2.close();    
        Debug.logInfo("--------> finish close session2");    
    */
    TransactionUtil.commit(transaction);
}

其中使用getCurrentSession()方法,在最后提交事务时候此session会自动关闭,不需手动关闭session。如果使用 openSession()方法则需要手动关闭打开的session。BugTypeOperate.createBugType()方法是我们自己的 JDBC实现,现在可以和Hibernate放到一个事务里面了。