Spring MVC+分布式事务+动态数据源配置

动态数据源配置:

<bean id="ds1" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close">
	<property name="uniqueResourceName" value="ds1"/>
	<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
	<property name="xaProperties">
		<props>
			<prop key="url">jdbc:mysql://localhost:3306/ds1?autoReconnect=true&autoReconnectForPools=true&failOverReadOnly=false&useUnicode=true&characterEncoding=utf-8</prop>
			<prop key="user">root</prop>
			<prop key="password">root</prop> 
		</props>
	</property>
	<property name="testQuery" value="select 1"></property>
</bean>
<bean id="ds2" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close">
	<property name="uniqueResourceName" value="ds2"/>
	<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
	<property name="xaProperties">
		<props>
			<prop key="url">jdbc:mysql://localhost:3306/ds2?autoReconnect=true&autoReconnectForPools=true&failOverReadOnly=false&useUnicode=true&characterEncoding=utf-8</prop>
			<prop key="user">root</prop>
			<prop key="password">ruanko</prop> 
		</props>
	</property>
	<property name="testQuery" value="select 1"></property>
</bean>
<bean id="onlineDynamicDataSource" class="com.gm.task.DynamicDataSource">
	<property name="targetDataSources">   
		<map key-type="java.lang.String"> 
			<entry key="ds1" value-ref="ds1"></entry>
			<entry key="ds2" value-ref="ds2"></entry>
		</map>   
	</property>   
	<property name="defaultTargetDataSource" ref="ds1"/>  
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
	<property name="dataSource">
		<ref bean="onlineDynamicDataSource" />
	</property>
	<property name="hibernateProperties">
		<props>
			<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
			<prop key="hibernate.cache.use_second_level_cache">true</prop>
			<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
			<prop key="hibernate.cache.use_query_cache">false</prop><!-- 缓存必须设置为false,否则切换数据源时会存在查询异常 -->
			<prop key="hibernate.generate_statistics">true</prop>
			<prop key="hibernate.show_sql">false</prop>
			<prop key="hibernate.format_sql">true</prop>
		</props>
	</property>
	<property name="mappingDirectoryLocations">
		<list>
			<value>
				/WEB-INF/classes/com/test/entity
			</value>
		</list>
	</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
	<property name="sessionFactory" ref="sessionFactory">
	</property>
</bean>

分布式事务配置:

<!-- atomikos事务管理器  --> 
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">  
	<description>UserTransactionManager</description>  
	<property name="forceShutdown">  
		<value>true</value>  
	</property>  
</bean>  

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">  
	<property name="transactionTimeout" value="300" />  
</bean>  

<!-- spring 事务管理器 -->  
<bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">  
	<property name="transactionManager">  
		<ref bean="atomikosTransactionManager" />  
	</property>  
	<property name="userTransaction">  
		<ref bean="atomikosUserTransaction" />  
	</property>  
</bean>  

<tx:advice id="txAdvice" transaction-manager="springTransactionManager">  
	<tx:attributes>  
		<tx:method name="save" rollback-for="Exception"/>  
		<tx:method name="*" rollback-for="Exception"/>  
	</tx:attributes>  
</tx:advice>  
<aop:config>  
	<aop:pointcut id="userOperation" expression="execution(* com.test.service.*.*.*.*(..))"/>  
	<aop:advisor advice-ref="txAdvice" pointcut-ref="userOperation"/>  
</aop:config> 
	
<context:component-scan base-package="com.gm.**" >
 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>	
<import resource="springmvc-servlet.xml" />

springmvc-servlet.xml中配置如下:

<context:component-scan base-package="com.gm.**" >
	<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
    
<context:annotation-config />

动态数据源的使用:

public class DynamicDataSourceHolder {

    private static final ThreadLocal<String> holder = new ThreadLocal<String>();

    public static void putDataSourceName(String name) {
        holder.set(name);
    }

    public static String getDataSourceName() {
        return holder.get();
    }

    public static void clear() {
        holder.remove();
    }
}
import java.sql.SQLException;
import java.util.Map;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    public void setTargetDataSources(Map targetDataSources) {
        super.setTargetDataSources(targetDataSources);
    }

    @Override
    public Object unwrap(Class iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class iface) throws SQLException {
        return false;
    }

    @Override
    protected Object determineCurrentLookupKey() {
        String dataSourceName = DynamicDataSourceHolder.getDataSourceName();
        return dataSourceName;
    }
}

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext context; // Spring应用上下文环境

    public void setApplicationContext(ApplicationContext context) throws BeansException {
        SpringContextUtil.context = context;
    }

    public static ApplicationContext getContext() {
        return context;
    }
}
ApplicationContext context = SpringContextUtil.getContext();
DynamicDataSourceHolder.putDataSourceName("ds1");
AtomikosDataSourceBean ds1 = (AtomikosDataSourceBean) context.getBean(dsString);
ds1.close();

以上是项目中的部分代码,欢迎各位发表意见及建议,共同探讨。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值