非托管环境下用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放到一个事务里面了。
非托管环境下用Tyrex集成Hibernate和jdbc实现JTA事务
最新推荐文章于 2025-03-04 15:32:58 发布