1. 程式人生 > >spring4+hibernate4+jotm 分散式事務

spring4+hibernate4+jotm 分散式事務

1.需要引入jar包:
		<dependency>
		    <groupId>com.experlog</groupId>
		    <artifactId>xapool</artifactId>
		    <version>1.5.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.ow2.carol/carol -->
		<dependency>
		    <groupId>org.ow2.carol</groupId>
		    <artifactId>carol</artifactId>
		    <version>3.0.10</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.ow2.carol/carol-iiop-delegate -->
		<dependency>
		    <groupId>org.ow2.carol</groupId>
		    <artifactId>carol-iiop-delegate</artifactId>
		    <version>3.0.10</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.ow2.carol/carol-interceptors -->
		<dependency>
		    <groupId>org.ow2.carol</groupId>
		    <artifactId>carol-interceptors</artifactId>
		    <version>1.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.objectweb.joram/joram-mom -->
		<dependency>
		    <groupId>org.objectweb.joram</groupId>
		    <artifactId>joram-mom</artifactId>
		    <version>5.0.9</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.objectweb.joram/joram-shared -->
		<dependency>
		    <groupId>org.objectweb.joram</groupId>
		    <artifactId>joram-shared</artifactId>
		    <version>5.7.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.ow2.jotm/jotm-datasource -->
		<dependency>
		    <groupId>org.ow2.jotm</groupId>
		    <artifactId>jotm-datasource</artifactId>
		    <version>2.2.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.ow2.jotm/jotm-core -->
		<dependency>
		    <groupId>org.ow2.jotm</groupId>
		    <artifactId>jotm-core</artifactId>
		    <version>2.2.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.ow2.jotm/jotm-standalone -->
		<dependency>
		    <groupId>org.ow2.jotm</groupId>
		    <artifactId>jotm-standalone</artifactId>
		    <version>2.2.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.ow2.jotm/jotm-jms -->
		<dependency>
		    <groupId>org.ow2.jotm</groupId>
		    <artifactId>jotm-jms</artifactId>
		    <version>2.2.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.ow2.spec.ee/ow2-jta-1.1-spec -->
		<dependency>
		    <groupId>org.ow2.spec.ee</groupId>
		    <artifactId>ow2-jta-1.1-spec</artifactId>
		    <version>1.0.13</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.ow2.spec.ee/ow2-connector-1.5-spec -->
		<dependency>
		    <groupId>org.ow2.spec.ee</groupId>
		    <artifactId>ow2-connector-1.5-spec</artifactId>
		    <version>1.0.13</version>
		</dependency>

2、手動建立JotmFactoryBean

import javax.naming.NamingException;
import javax.transaction.SystemException;

import org.objectweb.jotm.Current;
import org.objectweb.jotm.Jotm;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;

@SuppressWarnings("rawtypes")
public class JotmFactoryBean implements FactoryBean, DisposableBean {

	private Current jotmCurrent;

	private Jotm jotm;

	public JotmFactoryBean() throws NamingException {
		// Check for already active JOTM instance.
		this.jotmCurrent = Current.getCurrent();

		// If none found, create new local JOTM instance.
		if (this.jotmCurrent == null) {
			// Only for use within the current Spring context:
			// local, not bound to registry.
			this.jotm = new Jotm(true, false);
			this.jotmCurrent = Current.getCurrent();
		}
	}

	public void setDefaultTimeout(int defaultTimeout) {
		this.jotmCurrent.setDefaultTimeout(defaultTimeout);
		// The following is a JOTM oddity: should be used for demarcation
		// transaction only,
		// but is required here in order to actually get rid of JOTM's default
		// (60 seconds).
		try {
			this.jotmCurrent.setTransactionTimeout(defaultTimeout);
		} catch (SystemException ex) {
			// should never happen
		}
	}

	public Jotm getJotm() {
		return this.jotm;
	}

	public Object getObject() {
		return this.jotmCurrent;
	}

	public Class getObjectType() {
		return this.jotmCurrent.getClass();
	}

	public boolean isSingleton() {
		return true;
	}

	public void destroy() {
		if (this.jotm != null) {
			this.jotm.stop();
		}
	}

}
3、配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="  
http://www.springframework.org/schema/beans   
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
http://www.springframework.org/schema/tx   
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd  
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd  
http://www.springframework.org/schema/context   
http://www.springframework.org/schema/context/spring-context-4.0.xsd  
http://cxf.apache.org/jaxws  
http://cxf.apache.org/schemas/jaxws.xsd">
	<!-- jotm實體類 -->  
	<bean id="jotm" class="com.JotmFactoryBean"/>
	
	<bean id="postgresqlDataSource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
		<property name="dataSource">
			<bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
				<property name="transactionManager" ref="jotm" />
				<property name="driverName" value="org.postgresql.Driver"/>
				<property name="url" value="jdbc:postgresql://****:5432/***?characterEncoding=utf8" />
			</bean>
		</property>
		<property name="user" value="platform" />
		<property name="password" value="root" />
	</bean>
	<bean id="mysqlDataSource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
		<property name="dataSource">
			<bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
				<property name="transactionManager" ref="jotm" />
				<property name="driverName" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://****:3306/**?characterEncoding=utf8" />
			</bean>
		</property>
		<property name="user" value="root" />
		<property name="password" value="root" />
	</bean>
	
	<!-- 將hibernate資料來源注入sessionFactory -->
    <bean id="postgresqlSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
         <property name="dataSource" ref="postgresqlDataSource" /> 
        <property name="packagesToScan">
			<list>
				<value>com.entity</value>
			</list>
		</property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL81Dialect</prop>
                <prop key="hibernate.show_sql">true</prop>
   				<prop key="hibernate.use_outer_join">true</prop>
				<prop key="hibernate.jdbc.fetch_size">30</prop>
				<prop key="hibernate.jdbc.batch_size">30</prop>
				<prop key="hibernate.jdbc.batch_versioned_data">true</prop>
				<prop key="hibernate.cache.use_second_level_cache">true</prop>
				<prop key="hibernate.cache.use_query_cache">true</prop>
				<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
				<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
				<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
				<prop key="javax.persistence.validation.mode">auto</prop>
				<prop key="hibernate.search.default.directory_provider">filesystem</prop>
				<prop key="hibernate.search.default.indexBase">/luceneIndexes</prop>
				<prop key="hibernate.search.default.refresh">1800</prop>
				<prop key="hibernate.search.default.indexwriter.max_merge_docs">100</prop>
				<prop key="hibernate.search.default.indexwriter.ram_buffer_size">64</prop>
				<prop key="hibernate.search.default.optimizer.operation_limit.max">1000</prop>
				<prop key="hibernate.search.default.optimizer.transaction_limit.max">100</prop>
            </props>
        </property>
    </bean>
    
    <!-- 將hibernate資料來源注入sessionFactory -->
    <bean id="mysqlSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="mysqlDataSource" />
   		<property name="packagesToScan">
			<list>
				<value>com.entity</value>
			</list>
		</property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.use_outer_join">true</prop>
				<prop key="hibernate.jdbc.fetch_size">30</prop>
				<prop key="hibernate.jdbc.batch_size">30</prop>
				<prop key="hibernate.jdbc.batch_versioned_data">true</prop>
				<prop key="hibernate.cache.use_second_level_cache">true</prop>
				<prop key="hibernate.cache.use_query_cache">true</prop>
				<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
				<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
				<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
				<prop key="javax.persistence.validation.mode">auto</prop>
				<prop key="hibernate.search.default.directory_provider">filesystem</prop>
				<prop key="hibernate.search.default.indexBase">/luceneIndexes</prop>
				<prop key="hibernate.search.default.refresh">1800</prop>
				<prop key="hibernate.search.default.indexwriter.max_merge_docs">100</prop>
				<prop key="hibernate.search.default.indexwriter.ram_buffer_size">64</prop>
				<prop key="hibernate.search.default.optimizer.operation_limit.max">1000</prop>
				<prop key="hibernate.search.default.optimizer.transaction_limit.max">100</prop>
            </props>
        </property>
    </bean>
	
    <!-- spring 事務管理器 -->
    <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="userTransaction" ref="jotm" />
    </bean>
    
   	<!-- 使用annotation定義事務,對於要加入事物的類,只需對該類加 @Transactional  -->
    <tx:annotation-driven transaction-manager="springTransactionManager"/> 
    
        <!-- hibernate Dao層模板 -->
    <bean id="postgresqlHibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
        <property name="sessionFactory" ref="postgresqlSessionFactory"></property>
    </bean>
    
    <bean id="mysqlHibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
        <property name="sessionFactory" ref="mysqlSessionFactory"></property>
    </bean>
</beans>
4、例項:
	public void test() {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:conf/app-include.xml");
		BsSysUserProvider bsSysUserProvider = ctx.getBean(BsSysUserProvider.class);  
		BsSysRoleProvider bsSysRoleProvider = ctx.getBean(BsSysRoleProvider.class);
		
		bsSysUserProvider.save();
		
		bsSysRoleProvider.save();
	}
        @Resource(name="mysqlHibernateTemplate")
	private HibernateTemplate mysqlHibernateTemplate;
	
	mysqlHibernateTemplate.save(bsSysUser);