mybatis+spring动态数据源的配置

这个版本是看了网上很多版本整合而来

需要的多数据源操作类

/**
 * 数据源设置类
 * @author admin
 *
 */
public class DataSourceContextHolder {  
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  
    public static void setDbType(String dbType) {  
        contextHolder.set(dbType);  
    }  
    public static String getDbType() {  
        return ((String) contextHolder.get());  
    }  
    public static void clearDbType() {  
        contextHolder.remove();  
    }  
}  

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSourceKey {
    String value() default "";
}

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


public class DynamicDataSource extends AbstractRoutingDataSource {  
    @Override  
	protected Object determineCurrentLookupKey() {  
        return DataSourceContextHolder.getDbType();  
    }  
}  


import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

/**
 * 该方法为切面方法,保证我们在执行数据库操作前可以动态的切换数据源
 * 
 * Created by lxh5316 on 2016/6/15.
 */
@Component
@Aspect
public class MultipleDataSourceAspectAdvice {

    private Logger logger = LogManager.getLogger(MultipleDataSourceAspectAdvice.class);
    
    /**
     * 可以在执行方法之前和之后改变参数和返回值
     * @param joinPoint用于获取目标方法相关信息的参数
     * @return 最终的返回值
     * @throws Throwable
     */
    @Around("execution(* com.coffee.dao.*.*(..))")
    public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {

        logger.debug("--multiple data source aop--");
        Object object = joinPoint.getTarget();
        logger.debug("Target Class:"+object.getClass());
        DataSourceKey annotation = AnnotationUtils.findAnnotation(object.getClass(),DataSourceKey.class);

        if (null!=annotation){
            String value = annotation.value();
            if(null!=value&&value.length()>0){
                DataSourceContextHolder.setDbType(value);
                logger.debug("Data Source Key :"+value);
            }
        }else {//没有注解时设置dbtype为null,表示用默认值
        	DataSourceContextHolder.setDbType(null);
        }

        return joinPoint.proceed();
    }

}

配置文件:


application-context.xml

<?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:p="http://www.springframework.org/schema/p"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  
  
  
   <import resource="applicationContext-mybatis.xml"/>
   <import resource="application-transaction.xml"/>
    <!-- 使用spring自带的占位符替换功能 -->  
    <bean  
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
        <!-- 允许JVM参数覆盖 -->  
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />  
        <!-- 忽略没有找到的资源文件 -->  
        <property name="ignoreResourceNotFound" value="true" />  
        <!-- 配置资源文件 -->  
        <property name="locations">  
            <list>  
                <value>classpath:jdbc.properties</value>  
            </list>  
        </property>  
    </bean>  
  
    <context:component-scan base-package="com.coffee" />  
  
    <!-- 数据库连接池 :coffeeHubDataSource -->  
    <bean id="coffeeHubDataSource" class="com.alibaba.druid.pool.DruidDataSource"  
        destroy-method="close">  
        <!-- 数据库驱动 -->  
        <property name="driverClassName" value="${coffeeHub.jdbc.driver}" />  
        <!-- 相应驱动的jdbcUrl -->  
        <property name="url" value="${coffeeHub.jdbc.url}" />  
        <!-- 数据库的用户名 -->  
        <property name="username" value="${coffeeHub.jdbc.username}" />  
        <!-- 数据库的密码 -->  
        <property name="password" value="${coffeeHub.jdbc.password}" />  
      <!-- 初始化连接大小 -->
		<property name="initialSize" value="40"></property>
		<!-- 连接池最大数量 -->
		<property name="maxActive" value="40"></property>
		<!-- 连接池最大空闲 -->
		<property name="maxIdle" value="10"></property>
		<!-- 连接池最小空闲 -->
		<property name="minIdle" value="1"></property>
		<!-- 获取连接最大等待时间 -->
		<property name="maxWait" value="60000"></property>
    </bean>  
    
    <!-- 数据库连接池 :appServerDataSource -->  
    <bean id="appserverDataSource" class="com.alibaba.druid.pool.DruidDataSource"  
        destroy-method="close">  
        <!-- 数据库驱动 -->  
        <property name="driverClassName" value="${appserver.jdbc.driver}" />  
        <!-- 相应驱动的jdbcUrl -->  
        <property name="url" value="${appserver.jdbc.url}" />  
        <!-- 数据库的用户名 -->  
        <property name="username" value="${appserver.jdbc.username}" />  
        <!-- 数据库的密码 -->  
        <property name="password" value="${appserver.jdbc.password}" />  
       <!-- 初始化连接大小 -->
		<property name="initialSize" value="40"></property>
		<!-- 连接池最大数量 -->
		<property name="maxActive" value="40"></property>
		<!-- 连接池最大空闲 -->
		<property name="maxIdle" value="10"></property>
		<!-- 连接池最小空闲 -->
		<property name="minIdle" value="1"></property>
		<!-- 获取连接最大等待时间 -->
		<property name="maxWait" value="60000"></property>
    </bean>  
  
  
  
    <!-- 数据库连接池 -->  
    <bean id="dynamicDataSource" class="com.coffee.sys.DynamicDataSource">  
        <property name="targetDataSources">  
            <map key-type="java.lang.String">  
                <entry value-ref="coffeeHubDataSource" key="coffeeHubDataSource" />  
                <entry value-ref="appserverDataSource" key="appserverDataSource" />  
            </map>  
        </property>  
  
        <!-- 默认使用appserverDataSource的数据源 -->  
        <property name="defaultTargetDataSource" ref="coffeeHubDataSource" />  
    </bean>
   </beans>  
application-transaction.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	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.1.xsd    
                        http://www.springframework.org/schema/context    
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd
                        http://www.springframework.org/schema/aop 
					    http://www.springframework.org/schema/aop/spring-aop-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/util 
    					http://www.springframework.org/schema/util/spring-util-4.0.xsd   
                        http://www.springframework.org/schema/mvc    
                        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

	<!-- 定义事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 使用动态的数据源dynamicDataSource -->
		<property name="dataSource" ref="dynamicDataSource" />
	</bean>

	<!-- 定义事务策略 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!--所有以query开头的方法都是只读的 -->
			<tx:method name="query*" read-only="true" />
			<!--其他方法使用默认事务策略 -->
			<tx:method name="*" />
		</tx:attributes>
	</tx:advice>
	<!--pointcut元素定义一个切入点,execution中的第一个星号 用以匹配方法的返回类型, 这里星号表明匹配所有返回类型。 com.abc.dao.*.*(..)表明匹配cn.millery.mybatis.service包下的所有类的所有 
		方法 -->
	
	<!-- 设置切面编程 -->
	<aop:aspectj-autoproxy proxy-target-class="true" />
</beans>  

applicatioinContext-mybatis.xml

<?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:p="http://www.springframework.org/schema/p"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  
    <!-- 定义Mybatis的SqlSessionFactory --> 
     
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
        <!-- 定义数据源,数据源使用动态的数据源dynamicDataSource -->  
        <property name="dataSource" ref="dynamicDataSource" />  
        <!-- 指定mybatis全局配置文件 -->  
        <property name="configLocation" value="classpath:mybatis-config.xml" />  
        <!-- 扫描mapper目录以及子目录下的所有xml文件 -->  
        <property name="mapperLocations" value="classpath:mapper/*.xml" />  
        <!-- 别名扫描包 -->  
        <!-- <property name="typeAliasesPackage" value="com.coffee" />  -->
    </bean>  
    
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
		<property name="basePackage" value="com.coffee.dao" />
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
		<!-- <property name="annotationClass" value="org.springframework.stereotype.Repository"/>    -->  
	</bean>  
</beans>  

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE configuration  
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
  "http://mybatis.org/dtd/mybatis-3-config.dtd">  
<configuration>  
    <settings>  
        <!-- 开启驼峰自动映射 -->  
        <setting name="mapUnderscoreToCamelCase" value="true" />  
    </settings>  
</configuration>  

jdbc.properties

#db1   
db1.jdbc.driver=com.mysql.jdbc.Driver  
db1.jdbc.url=jdbc:mysql://127.0.0.1:3306/db1?useUnicode=true&characterEncoding=utf8
db1.jdbc.username=root
db1.jdbc.password=123456
   
#db2 
db2.jdbc.driver=com.mysql.jdbc.Driver  
db2.jdbc.url=jdbc:mysql://127.0.0.1:3306/db2?useUnicode=true&characterEncoding=utf8
db2.jdbc.username=root
db2.jdbc.password=123456



测试类:



核心是在dao类上加上注解即可

import org.springframework.stereotype.Repository;

import com.coffee.bean.AccessRuleBean;
import com.coffee.constant.Constants;
import com.coffee.sys.DataSourceKey;

/**
 * 
 * @author admin
 *
 */

@Repository
@DataSourceKey(value=Constants.APP_SERVER_DATA_SOURCE)
public interface AccessRuleDao {
	
	AccessRuleBean getAccessRule();	

}




其余业务代码忽略,自行书写

测试代码:

/**
 * 多数据源测试类
 * @author admin
 *
 */
public class MutiDataSourceTest {

	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		 ApplicationContext ac = new ClassPathXmlApplicationContext("application-context.xml");
		 System.out.println("start ...");
		 ContractService cs = (ContractService)ac.getBean("contractService");
		 
		 ContractBean contract = cs.getContract();
		 System.out.println(contract.getBorrowerName());
		 System.out.println("end ...");
		 
		 
		 AccessRuleService accessRuleService = (AccessRuleService)ac.getBean("accessRuleService");
//		 DataSourceContextHolder.setDbType("appserverDataSource");
		 AccessRuleBean accessRule = accessRuleService.getAccessRule();
		 String serialno = accessRule.getSerialno();
		 
		 System.out.println("serialno:" + serialno);
		 
		 
		 System.out.println("end ...");
		 
		 contract = cs.getContract();
		 System.out.println(contract.getBorrowerName());
	}











  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值