动态数据源配置:
<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();
以上是项目中的部分代码,欢迎各位发表意见及建议,共同探讨。