您的位置:首页 > 编程语言 > Java开发

Spring分布式事务在service中动态切换数据源

2017-05-20 16:26 429 查看



Spring分布式事务在service中动态切换数据源

项目采用的是struts2+spring+ibatis架构,下面是关键部分代码:

applicationContext.xml:

[html] view plain copy print?<?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:context=“http://www.springframework.org/schema/context”
xmlns:aop=“http://www.springframework.org/schema/aop”
xmlns:tx=“http://www.springframework.org/schema/tx”
xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd” default-autowire=“byName” default-lazy-init=“false”>

<context:component-scan base-package=“com.ssi.*” />
<!– 属性文件读入 –>
<bean id=“propertyConfigurer” class=“org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>
<property name=“locations”>
<list>
<value>classpath*:jdbc.properties</value>
</list>
</property>
</bean>

<!– 配置sqlMapclient –>
<bean id=“sqlMapClient” class=“org.springframework.orm.ibatis.SqlMapClientFactoryBean”>
<property name=“configLocation” value=“classpath:ibatis-sqlmap-config.xml” />
<property name=“dataSource” ref=“dataSource” />
</bean>

<bean id=“sqlMapClient1” class=“org.springframework.orm.ibatis.SqlMapClientFactoryBean”>
<property name=“configLocation” value=“classpath:ibatis-sqlmap-config.xml” />
<property name=“dataSource” ref=“db1” />
</bean>
<bean id=“sqlMapClient2” class=“org.springframework.orm.ibatis.SqlMapClientFactoryBean”>
<property name=“configLocation” value=“classpath:ibatis-sqlmap-config.xml” />
<property name=“dataSource” ref=“db2” />
</bean>
<bean id=“sqlMapClientCenter” class=“org.springframework.orm.ibatis.SqlMapClientFactoryBean”>
<property name=“configLocation” value=“classpath:ibatis-sqlmap-config.xml” />
<property name=“dataSource” ref=“center” />
</bean>

<bean id=“dynamicSqlMapClientDaoSupport” class=“com.ssi.dao.DynamicSqlClientDaoSupport”>
<property name=“targetSqlMapClients”>
<map>
<entry key=“db1” value-ref=“sqlMapClient1” />
<entry key=“db2” value-ref=“sqlMapClient2” />
<entry key=“center” value-ref=“sqlMapClientCenter” />
</map>
</property>
<property name=“defaultSqlMapClient” ref=“sqlMapClientCenter” />
</bean>
<bean id=“ibatisDaoSupport” class=“com.ssi.dao.IbatisDaoSupport” parent=“dynamicSqlMapClientDaoSupport”></bean>

<bean id=“userDao” class=“com.ssi.dao.impl.UserDaoImpl” parent=“ibatisDaoSupport”></bean>

<!– 支持 @AspectJ 标记–>
<aop:aspectj-autoproxy proxy-target-class=“true”/>

<!– 配置JTA的事务管理器 –>
<bean id=“atomikosTransactionManager” class=“com.atomikos.icatch.jta.UserTransactionManager” init-method=“init” destroy-method=“close”>
<property name=“forceShutdown” value=“true” />
</bean>
<bean id=“atomikosUserTransaction” class=“com.atomikos.icatch.jta.UserTransactionImp”>
<property name=“transactionTimeout” value=“300” />
</bean>
<bean id=“springTransactionManager” class=“org.springframework.transaction.jta.JtaTransactionManager”>
<property name=“transactionManager” ref=“atomikosTransactionManager” />
<property name=“userTransaction” ref=“atomikosUserTransaction” />
</bean>
<!– 配置通知 –>
<tx:advice id=“txAdvice” transaction-manager=“springTransactionManager”>
<tx:attributes>
&
1b024
nbsp; <tx:method name=“*” rollback-for=“Exception,RuntimeException,com.ssi.exception.SystemException” propagation=“REQUIRED” />
</tx:attributes>
</tx:advice>

<!– 以AspectJ方式 定义 AOP –>

<aop:config>
<aop:advisor pointcut=“execution(* com.ssi.service..*Service*.*(..))” advice-ref=“txAdvice” />
</aop:config>

<!– spring 定时器任务开始 –>
<bean name=“job” class=“org.springframework.scheduling.quartz.JobDetailBean”>
<property name=“jobClass”>
<value>com.ssi.action.TimerAction</value>
</property>
<property name=“jobDataAsMap”>
<map>
<!– timeout属性设定了当服务器启动后过10秒钟首次调用你的JobAction –>
<entry key=“timeout”>
<value>10</value>
</entry>
</map>
</property>
</bean>
<bean id=“cronTrigger” class=“org.springframework.scheduling.quartz.CronTriggerBean”>
<property name=“jobDetail”>
<ref bean=“job”/>
</property>
<property name=“cronExpression”>
<value>0 53 15 ? * MON-FRI</value>
</property>
</bean>
<bean class=“org.springframework.scheduling.quartz.SchedulerFactoryBean” autowire=“no”>
<property name=“triggers”>
<list>
<ref local=“cronTrigger”/>
</list>
</property>
</bean>
<!– spring 定时器任务结束 –>

</beans>


<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd" default-autowire="byName" default-lazy-init="false">

<context:component-scan base-package="com.ssi.*" />
<!-- 属性文件读入 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:jdbc.properties</value>
</list>
</property>
</bean>

<!-- 配置sqlMapclient -->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:ibatis-sqlmap-config.xml" />
<property name="dataSource" ref="dataSource" />
</bean>

<bean id="sqlMapClient1" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:ibatis-sqlmap-config.xml" />
<property name="dataSource" ref="db1" />
</bean>
<bean id="sqlMapClient2" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:ibatis-sqlmap-config.xml" />
<property name="dataSource" ref="db2" />
</bean>
<bean id="sqlMapClientCenter" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:ibatis-sqlmap-config.xml" />
<property name="dataSource" ref="center" />
</bean>

<bean id="dynamicSqlMapClientDaoSupport" class="com.ssi.dao.DynamicSqlClientDaoSupport">
<property name="targetSqlMapClients">
<map>
<entry key="db1" value-ref="sqlMapClient1" />
<entry key="db2" value-ref="sqlMapClient2" />
<entry key="center" value-ref="sqlMapClientCenter" />
</map>
</property>
<property name="defaultSqlMapClient" ref="sqlMapClientCenter" />
</bean>
<bean id="ibatisDaoSupport" class="com.ssi.dao.IbatisDaoSupport" parent="dynamicSqlMapClientDaoSupport"></bean>

<bean id="userDao" class="com.ssi.dao.impl.UserDaoImpl" parent="ibatisDaoSupport"></bean>

<!-- 支持 @AspectJ 标记-->
<aop:aspectj-autoproxy proxy-target-class="true"/>

<!-- 配置JTA的事务管理器 -->
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"    init-method="init" destroy-method="close">
<property name="forceShutdown" value="true" />
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
<bean id="springTransactionManager"  class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
</bean>
<!-- 配置通知 -->
<tx:advice id="txAdvice" transaction-manager="springTransactionManager">
<tx:attributes>
<tx:method name="*" rollback-for="Exception,RuntimeException,com.ssi.exception.SystemException" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>

<!-- 以AspectJ方式 定义 AOP -->

<aop:config>
<aop:advisor pointcut="execution(* com.ssi.service..*Service*.*(..))" advice-ref="txAdvice" />
</aop:config>

<!-- spring 定时器任务开始 -->
<bean name="job" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>com.ssi.action.TimerAction</value>
</property>
<property name="jobDataAsMap">
<map>
<!-- timeout属性设定了当服务器启动后过10秒钟首次调用你的JobAction -->
<entry key="timeout">
<value>10</value>
</entry>
</map>
</property>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="job"/>
</property>
<property name="cronExpression">
<value>0 53 15 ? * MON-FRI</value>
</property>
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no">
<property name="triggers">
<list>
<ref local="cronTrigger"/>
</list>
</property>
</bean>
<!-- spring 定时器任务结束 -->

</beans>


[html] view plain copy print?


applicationContext-datasource.xml

[html] view plain copy print?<?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”
xsi:schemaLocation=” http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd”>

<!–指定Spring配置中用到的属性文件–>
<bean id=“propertyConfig” class=“org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>
<property name=“locations”>
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!– JTA 数据源配置 –>
<bean id=“center” class=“com.atomikos.jdbc.AtomikosDataSourceBean” init-method=“init” destroy-method=“close”>
<property name=“uniqueResourceName”>
<value>mysql/center</value>
</property>
<property name=“xaDataSourceClassName”>
<value>{jta.driver.className}</span><span class="tag"></</span><span class="tag-name">value</span><span class="tag">></span><span>  </span></span></li><li class=""><span>        <span class="tag"></</span><span class="tag-name">property</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>        <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"xaProperties"</span><span class="tag">></span><span>  </span></span></li><li class=""><span>            <span class="tag"><</span><span class="tag-name">props</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>                <span class="tag"><</span><span class="tag-name">prop</span><span> </span><span class="attribute">key</span><span>=</span><span class="attribute-value">"url"</span><span class="tag">></span><span>{center.jdbc.driver.url}</prop>
<prop key=“user”>{center.sql.user.name}</span><span class="tag"></</span><span class="tag-name">prop</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>                <span class="tag"><</span><span class="tag-name">prop</span><span> </span><span class="attribute">key</span><span>=</span><span class="attribute-value">"password"</span><span class="tag">></span><span>{center.sql.user.password}</prop>
</props>
</property>
<property name=“testQuery” value=“select 1” />
<property name=“poolSize”>
<value>{poolsize}</span><span class="tag"></</span><span class="tag-name">value</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>        <span class="tag"></</span><span class="tag-name">property</span><span class="tag">></span><span>  </span></span></li><li class=""><span>        <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"maxPoolSize"</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>            <span class="tag"><</span><span class="tag-name">value</span><span class="tag">></span><span>{maxPoolSize}</value>
</property>
<property name=“borrowConnectionTimeout”><value>{borrowConnectionTimeout}</span><span class="tag"></</span><span class="tag-name">value</span><span class="tag">></span><span class="tag"></</span><span class="tag-name">property</span><span class="tag">></span><span>  </span></span></li><li class=""><span>    <span class="tag"></</span><span class="tag-name">bean</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>      </span></li><li class=""><span>    <span class="tag"><</span><span class="tag-name">bean</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"db1"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.atomikos.jdbc.AtomikosDataSourceBean"</span><span> </span><span class="attribute">init-method</span><span>=</span><span class="attribute-value">"init"</span><span> </span><span class="attribute">destroy-method</span><span>=</span><span class="attribute-value">"close"</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>        <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"uniqueResourceName"</span><span class="tag">></span><span>  </span></span></li><li class=""><span>            <span class="tag"><</span><span class="tag-name">value</span><span class="tag">></span><span>mysql/db1</span><span class="tag"></</span><span class="tag-name">value</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>        <span class="tag"></</span><span class="tag-name">property</span><span class="tag">></span><span>  </span></span></li><li class=""><span>        <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"xaDataSourceClassName"</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>            <span class="tag"><</span><span class="tag-name">value</span><span class="tag">></span><span>{jta.driver.className}</value>
</property>
<property name=“xaProperties”>
<props>
<prop key=“url”>{db1.jdbc.driver.url}</span><span class="tag"></</span><span class="tag-name">prop</span><span class="tag">></span><span>  </span></span></li><li class=""><span>                <span class="tag"><</span><span class="tag-name">prop</span><span> </span><span class="attribute">key</span><span>=</span><span class="attribute-value">"user"</span><span class="tag">></span><span>{company.sql.user.name}</prop>
<prop key=“password”>{company.sql.user.password}</span><span class="tag"></</span><span class="tag-name">prop</span><span class="tag">></span><span>  </span></span></li><li class=""><span>            <span class="tag"></</span><span class="tag-name">props</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>        <span class="tag"></</span><span class="tag-name">property</span><span class="tag">></span><span>  </span></span></li><li class=""><span>        <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"testQuery"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"select 1"</span><span> </span><span class="tag">/></span><span>  </span></span></li><li class="alt"><span>        <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"poolSize"</span><span class="tag">></span><span>  </span></span></li><li class=""><span>            <span class="tag"><</span><span class="tag-name">value</span><span class="tag">></span><span>{poolsize}</value>
</property>
<property name=“maxPoolSize”>
<value>{maxPoolSize}</span><span class="tag"></</span><span class="tag-name">value</span><span class="tag">></span><span>  </span></span></li><li class=""><span>        <span class="tag"></</span><span class="tag-name">property</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>        <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"borrowConnectionTimeout"</span><span class="tag">></span><span class="tag"><</span><span class="tag-name">value</span><span class="tag">></span><span>{borrowConnectionTimeout}</value></property>
</bean>
<bean id=“db2” class=“com.atomikos.jdbc.AtomikosDataSourceBean” init-method=“init” destroy-method=“close”>
<property name=“uniqueResourceName”>
<value>mysql/db2</value>
</property>
<property name=“xaDataSourceClassName”>
<value>{jta.driver.className}</span><span class="tag"></</span><span class="tag-name">value</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>        <span class="tag"></</span><span class="tag-name">property</span><span class="tag">></span><span>  </span></span></li><li class=""><span>        <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"xaProperties"</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>            <span class="tag"><</span><span class="tag-name">props</span><span class="tag">></span><span>  </span></span></li><li class=""><span>                <span class="tag"><</span><span class="tag-name">prop</span><span> </span><span class="attribute">key</span><span>=</span><span class="attribute-value">"url"</span><span class="tag">></span><span>{db2.jdbc.driver.url}</prop>
<prop key=“user”>{company.sql.user.name}</span><span class="tag"></</span><span class="tag-name">prop</span><span class="tag">></span><span>  </span></span></li><li class=""><span>                <span class="tag"><</span><span class="tag-name">prop</span><span> </span><span class="attribute">key</span><span>=</span><span class="attribute-value">"password"</span><span class="tag">></span><span>{company.sql.user.password}</prop>
</props>
</property>
<property name=“testQuery” value=“select 1” />
<property name=“poolSize”>
<value>{poolsize}</span><span class="tag"></</span><span class="tag-name">value</span><span class="tag">></span><span>  </span></span></li><li class=""><span>        <span class="tag"></</span><span class="tag-name">property</span><span class="tag">></span><span>  </span></span></li><li class="alt"><span>        <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"maxPoolSize"</span><span class="tag">></span><span>  </span></span></li><li class=""><span>            <span class="tag"><</span><span class="tag-name">value</span><span class="tag">></span><span>{maxPoolSize}</value>
</property>
<property name=“borrowConnectionTimeout”><value>${borrowConnectionTimeout}</value></property>
</bean>

<bean id=“dataSource” class=“com.ssi.datasource.DynamicDataSource”>
<property name=“targetDataSources”>
<map key-type=“java.lang.String”>
<entry key=“db1” value-ref=“db1” />
<entry key=“db2” value-ref=“db2” />
<entry key=“center” value-ref=“center” />
</map>
</property>
<property name=“defaultTargetDataSource” ref=“center” />
</bean>
</beans>


<?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"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<!--指定Spring配置中用到的属性文件-->
<bean id="propertyConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!-- JTA 数据源配置 -->
<bean id="center" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName">
<value>mysql/center</value>
</property>
<property name="xaDataSourceClassName">
<value>${jta.driver.className}</value>
</property>
<property name="xaProperties">
<props>
<prop key="url">${center.jdbc.driver.url}</prop>
<prop key="user">${center.sql.user.name}</prop>
<prop key="password">${center.sql.user.password}</prop>
</props>
</property>
<property name="testQuery" value="select 1" />
<property name="poolSize">
<value>${poolsize}</value>
</property>
<property name="maxPoolSize">
<value>${maxPoolSize}</value>
</property>
<property name="borrowConnectionTimeout"><value>${borrowConnectionTimeout}</value></property>
</bean>

<bean id="db1" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName">
<value>mysql/db1</value>
</property>
<property name="xaDataSourceClassName">
<value>${jta.driver.className}</value>
</property>
<property name="xaProperties">
<props>
<prop key="url">${db1.jdbc.driver.url}</prop>
<prop key="user">${company.sql.user.name}</prop>
<prop key="password">${company.sql.user.password}</prop>
</props>
</property>
<property name="testQuery" value="select 1" />
<property name="poolSize">
<value>${poolsize}</value>
</property>
<property name="maxPoolSize">
<value>${maxPoolSize}</value>
</property>
<property name="borrowConnectionTimeout"><value>${borrowConnectionTimeout}</value></property>
</bean>
<bean id="db2" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName">
<value>mysql/db2</value>
</property>
<property name="xaDataSourceClassName">
<value>${jta.driver.className}</value>
</property>
<property name="xaProperties">
<props>
<prop key="url">${db2.jdbc.driver.url}</prop>
<prop key="user">${company.sql.user.name}</prop>
<prop key="password">${company.sql.user.password}</prop>
</props>
</property>
<property name="testQuery" value="select 1" />
<property name="poolSize">
<value>${poolsize}</value>
</property>
<property name="maxPoolSize">
<value>${maxPoolSize}</value>
</property>
<property name="borrowConnectionTimeout"><value>${borrowConnectionTimeout}</value></property>
</bean>

<bean id="dataSource" class="com.ssi.datasource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="db1" value-ref="db1" />
<entry key="db2" value-ref="db2" />
<entry key="center" value-ref="center" />
</map>
</property>
<property name="defaultTargetDataSource" ref="center" />
</bean>
</beans>


DynamicSqlClientDaoSupport.Java

[java] view plain copy print?package com.ssi.dao;

import java.util.Map;

import javax.sql.DataSource;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.support.DaoSupport;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.util.Assert;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.ssi.datasource.DbContextHolder;

public class DynamicSqlClientDaoSupport extends DaoSupport implements InitializingBean{

private SqlMapClientTemplate sqlMapClientTemplate = new SqlMapClientTemplate();
private Map<String,SqlMapClient> targetSqlMapClients;
private SqlMapClient defaultSqlMapClient;
private boolean externalTemplate = false;

/**
* Set the JDBC DataSource to be used by this DAO.
* Not required: The SqlMapClient might carry a shared DataSource.
* @see #setSqlMapClient
*/
public final void setDataSource(DataSource dataSource) {
if (!this.externalTemplate) {
this.sqlMapClientTemplate.setDataSource(dataSource);
}
}

/**
* Return the JDBC DataSource used by this DAO.
*/
public final DataSource getDataSource() {
return this.sqlMapClientTemplate.getDataSource();
}

/**
* Set the iBATIS Database Layer SqlMapClient to work with.
* Either this or a “sqlMapClientTemplate” is required.
* @see #setSqlMapClientTemplate
*/
public final void setSqlMapClient(SqlMapClient sqlMapClient) {
if (!this.externalTemplate) {
this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient);
}
}

/**
* Return the iBATIS Database Layer SqlMapClient that this template works with.
*/
public final SqlMapClient getSqlMapClient() {
return this.sqlMapClientTemplate.getSqlMapClient();
}

/**
* Set the SqlMapClientTemplate for this DAO explicitly,
* as an alternative to specifying a SqlMapClient.
* @see #setSqlMapClient
*/
public final void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate) {
Assert.notNull(sqlMapClientTemplate, ”SqlMapClientTemplate must not be null”);
this.sqlMapClientTemplate = sqlMapClientTemplate;
this.externalTemplate = true;
}

/**
* Return the SqlMapClientTemplate for this DAO,
* pre-initialized with the SqlMapClient or set explicitly.
*/
public final SqlMapClientTemplate getSqlMapClientTemplate() {
String dbtype = DbContextHolder.getDbType();
if(targetSqlMapClients!=null&&targetSqlMapClients.containsKey(dbtype)){
SqlMapClient sqlMapClient = targetSqlMapClients.get(dbtype);
sqlMapClientTemplate = new SqlMapClientTemplate(sqlMapClient);
}
return this.sqlMapClientTemplate;
}

@Override
protected final void checkDaoConfig() {
if (!this.externalTemplate) {
this.sqlMapClientTemplate.afterPropertiesSet();
}
}

public Map<String, SqlMapClient> getTargetSqlMapClients() {
return targetSqlMapClients;
}

public void setTargetSqlMapClients(Map<String, SqlMapClient> targetSqlMapClients) {
this.targetSqlMapClients = targetSqlMapClients;
}

public SqlMapClient getDefaultSqlMapClient() {
return defaultSqlMapClient;
}

public void setDefaultSqlMapClient(SqlMapClient defaultSqlMapClient) {
this.defaultSqlMapClient = defaultSqlMapClient;
}
}


package com.ssi.dao;

import java.util.Map;

import javax.sql.DataSource;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.support.DaoSupport;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.util.Assert;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.ssi.datasource.DbContextHolder;

public class DynamicSqlClientDaoSupport extends DaoSupport implements InitializingBean{

private SqlMapClientTemplate sqlMapClientTemplate = new SqlMapClientTemplate();
private Map<String,SqlMapClient> targetSqlMapClients;
private SqlMapClient defaultSqlMapClient;
private boolean externalTemplate = false;

/**
* Set the JDBC DataSource to be used by this DAO.
* Not required: The SqlMapClient might carry a shared DataSource.
* @see #setSqlMapClient
*/
public final void setDataSource(DataSource dataSource) {
if (!this.externalTemplate) {
this.sqlMapClientTemplate.setDataSource(dataSource);
}
}

/**
* Return the JDBC DataSource used by this DAO.
*/
public final DataSource getDataSource() {
return this.sqlMapClientTemplate.getDataSource();
}

/**
* Set the iBATIS Database Layer SqlMapClient to work with.
* Either this or a "sqlMapClientTemplate" is required.
* @see #setSqlMapClientTemplate
*/
public final void setSqlMapClient(SqlMapClient sqlMapClient) {
if (!this.externalTemplate) {
this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient);
}
}

/**
* Return the iBATIS Database Layer SqlMapClient that this template works with.
*/
public final SqlMapClient getSqlMapClient() {
return this.sqlMapClientTemplate.getSqlMapClient();
}

/**
* Set the SqlMapClientTemplate for this DAO explicitly,
* as an alternative to specifying a SqlMapClient.
* @see #setSqlMapClient
*/
public final void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate) {
Assert.notNull(sqlMapClientTemplate, "SqlMapClientTemplate must not be null");
this.sqlMapClientTemplate = sqlMapClientTemplate;
this.externalTemplate = true;
}

/**
* Return the SqlMapClientTemplate for this DAO,
* pre-initialized with the SqlMapClient or set explicitly.
*/
public final SqlMapClientTemplate getSqlMapClientTemplate() {
String dbtype = DbContextHolder.getDbType();
if(targetSqlMapClients!=null&&targetSqlMapClients.containsKey(dbtype)){
SqlMapClient sqlMapClient = targetSqlMapClients.get(dbtype);
sqlMapClientTemplate = new SqlMapClientTemplate(sqlMapClient);
}
return this.sqlMapClientTemplate;
}

@Override
protected final void checkDaoConfig() {
if (!this.externalTemplate) {
this.sqlMapClientTemplate.afterPropertiesSet();
}
}

public Map<String, SqlMapClient> getTargetSqlMapClients() {
return targetSqlMapClients;
}

public void setTargetSqlMapClients(Map<String, SqlMapClient> targetSqlMapClients) {
this.targetSqlMapClients = targetSqlMapClients;
}

public SqlMapClient getDefaultSqlMapClient() {
return defaultSqlMapClient;
}

public void setDefaultSqlMapClient(SqlMapClient defaultSqlMapClient) {
this.defaultSqlMapClient = defaultSqlMapClient;
}
}
IbatisDaoSupport.java

[java] view plain copy print?package com.ssi.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.ibatis.SqlMapClientCallback;

import com.ibatis.sqlmap.client.SqlMapExecutor;
@SuppressWarnings(“unchecked”)
public class IbatisDaoSupport<Entity> extends DynamicSqlClientDaoSupport implements IEntityDao<Entity> {

protected final Log log = LogFactory.getLog(getClass());

public Entity get(String sqlId, Serializable id) {
return (Entity) getSqlMapClientTemplate().queryForObject(sqlId, id);
}
public Entity getByParamMap(String sqlId, Object param) {
return (Entity) getSqlMapClientTemplate().queryForObject(sqlId, param);
}
public Object save(String sqlId, Object o) {
return getSqlMapClientTemplate().insert(sqlId, o);
}
public Object batchSave(final String sqlId,final List<Entity> entityList) throws Exception{
// 执行回调
return getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
// 实现回调接口
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException{
// 开始批处理
executor.startBatch();
for (Entity entity : entityList) {
executor.insert(sqlId, entity);
}
return executor.executeBatch();
}

});

}
public Integer remove(String sqlId, Object o) {
return getSqlMapClientTemplate().delete(sqlId, o);

}

public Integer removeById(String sqlId, Serializable id) {
return getSqlMapClientTemplate().delete(sqlId, id);
}

public Integer update(String sqlId, Object o) {
return getSqlMapClientTemplate().update(sqlId, o);

}
public Long totalCount(String sqlId, Object o){
return (Long) getSqlMapClientTemplate().queryForObject(sqlId, o);
}
public List<Entity> pagedList(String sqlId, Map<String, Object> map,int pageSize, int pageNum) {
int start = (pageNum - 1) * pageSize;
map.put(”start”, start);
map.put(”pageSize”, pageSize);
List<Entity> list = getSqlMapClientTemplate().queryForList(sqlId, map);
return list;
}
public List<Entity> list(String sqlId,Object o){
return getSqlMapClientTemplate().queryForList(sqlId,o);
}
public List<Entity> list(String sqlId){
return getSqlMapClientTemplate().queryForList(sqlId);
}

}


package com.ssi.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.ibatis.SqlMapClientCallback;

import com.ibatis.sqlmap.client.SqlMapExecutor;
@SuppressWarnings("unchecked")
public class IbatisDaoSupport<Entity> extends DynamicSqlClientDaoSupport implements IEntityDao<Entity> {

protected final Log log = LogFactory.getLog(getClass());

public Entity get(String sqlId, Serializable id) {
return (Entity) getSqlMapClientTemplate().queryForObject(sqlId, id);
}
public Entity getByParamMap(String sqlId, Object param) {
return (Entity) getSqlMapClientTemplate().queryForObject(sqlId, param);
}
public Object save(String sqlId, Object o) {
return getSqlMapClientTemplate().insert(sqlId, o);
}
public Object batchSave(final String sqlId,final List<Entity> entityList) throws Exception{
// 执行回调
return getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
// 实现回调接口
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException{
// 开始批处理
executor.startBatch();
for (Entity entity : entityList) {
executor.insert(sqlId, entity);
}
return executor.executeBatch();
}

});

}
public Integer remove(String sqlId, Object o) {
return getSqlMapClientTemplate().delete(sqlId, o);

}

public Integer removeById(String sqlId, Serializable id) {
return getSqlMapClientTemplate().delete(sqlId, id);
}

public Integer update(String sqlId, Object o) {
return getSqlMapClientTemplate().update(sqlId, o);

}
public Long totalCount(String sqlId, Object o){
return (Long) getSqlMapClientTemplate().queryForObject(sqlId, o);
}
public List<Entity> pagedList(String sqlId, Map<String, Object> map,int pageSize, int pageNum) {
int start = (pageNum - 1) * pageSize;
map.put("start", start);
map.put("pageSize", pageSize);
List<Entity> list = getSqlMapClientTemplate().queryForList(sqlId, map);
return list;
}
public List<Entity> list(String sqlId,Object o){
return getSqlMapClientTemplate().queryForList(sqlId,o);
}
public List<Entity> list(String sqlId){
return getSqlMapClientTemplate().queryForList(sqlId);
}

}


UserDaoImpl.java:

[java] view plain copy print?package com.ssi.dao.impl;

import org.springframework.stereotype.Repository;

import com.ssi.dao.IUserDao;
import com.ssi.dao.IbatisDaoSupport;
import com.ssi.model.User;
@Repository(“userDao”)
public class UserDaoImpl extends IbatisDaoSupport<User> implements IUserDao {
public Integer addUser(User user) throws Exception{
return (Integer) this.save(“User.insert”, user);
}
}


package com.ssi.dao.impl;

import org.springframework.stereotype.Repository;

import com.ssi.dao.IUserDao;
import com.ssi.dao.IbatisDaoSupport;
import com.ssi.model.User;
@Repository("userDao")
public class UserDaoImpl extends IbatisDaoSupport<User> implements IUserDao {
public Integer addUser(User user) throws Exception{
return (Integer) this.save("User.insert", user);
}
}


UserServiceImpl.java

[java] view plain copy print?package com.ssi.service.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.ssi.dao.IUserDao;
import com.ssi.datasource.DbContextHolder;
import com.ssi.model.User;
import com.ssi.service.IUserService;

@Service(“userService”)
public class UserServiceImpl implements IUserService {
@Resource private IUserDao userDao;
/**
* 测试在service中切换数据源 异常是否回滚
*/
public void addUser(User user) throws Exception{
DbContextHolder.setDbType(”db1”);
userDao.addUser(user);
DbContextHolder.setDbType(”db2”);
user.setUserName(”user2”);
userDao.addUser(user);
DbContextHolder.setDbType(”center”);
user.setUserName(”user3”);
userDao.addUser(user);
//System.out.println(1/0);
}
}


package com.ssi.service.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.ssi.dao.IUserDao;
import com.ssi.datasource.DbContextHolder;
import com.ssi.model.User;
import com.ssi.service.IUserService;

@Service("userService")
public class UserServiceImpl implements IUserService {
@Resource private IUserDao userDao;
/**
* 测试在service中切换数据源 异常是否回滚
*/
public void addUser(User user) throws Exception{
DbContextHolder.setDbType("db1");
userDao.addUser(user);
DbContextHolder.setDbType("db2");
user.setUserName("user2");
userDao.addUser(user);
DbContextHolder.setDbType("center");
user.setUserName("user3");
userDao.addUser(user);
//System.out.println(1/0);
}
}


DynamicDataSource.java:

[java] view plain copy print?public class DynamicDataSource extends AbstractRoutingDataSource { static Logger log = Logger.getLogger(DynamicDataSource.class); protected Object determineCurrentLookupKey() { return DbContextHolder.getDbType(); } }


public class DynamicDataSource extends AbstractRoutingDataSource {

static Logger log = Logger.getLogger(DynamicDataSource.class);

protected Object determineCurrentLookupKey() {
return DbContextHolder.getDbType();
}

}
DbContextHolder.java:

[java] view plain copy print?public class DbContextHolder { private static final ThreadLocal contextHolder = new ThreadLocal(); public static void setDbType(String dbType) { contextHolder.set(dbType); } public static String getDbType() { return (String) contextHolder.get(); } public static void clearDbType() { contextHolder.remove(); } }


public class DbContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal();

public static void setDbType(String dbType) {
contextHolder.set(dbType);
}

public static String getDbType() {
return (String) contextHolder.get();
}

public static void clearDbType() {
contextHolder.remove();
}

}


三个数据库:dbcenter、db1、db2 表结构均相同

脚本:

[sql] view plain copy print?DROP TABLE IF EXISTS `tb_user`; CREATE TABLE `tb_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(20) DEFAULT NULL, `password` varchar(60) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `tb_user`;

CREATE TABLE `tb_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(20) DEFAULT NULL,
`password` varchar(60) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


单元测试

[java] view plain copy print?public class JunitTest{
public ApplicationContext cxt;
@Test
public void init() throws Exception{
cxt = new ClassPathXmlApplicationContext(new String[] {“applicationContext.xml”,“applicationContext-datasource.xml”});
testInsertUser();

}

private void testInsertUser() throws Exception{
IUserService userService = (IUserService)cxt.getBean(”userService”);
User user = new User();
user.setUserName(”user1”);
user.setPassword(”0”);
userService.addUser(user);
}

private void testInsertUser2() throws Exception{

}


public class JunitTest{
public ApplicationContext cxt;
@Test
public void init() throws Exception{
cxt = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml","applicationContext-datasource.xml"});
testInsertUser();

}

private void testInsertUser() throws Exception{
IUserService userService = (IUserService)cxt.getBean("userService");
User user = new User();
user.setUserName("user1");
user.setPassword("0");
userService.addUser(user);
}

private void testInsertUser2() throws Exception{

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring