zoukankan      html  css  js  c++  java
  • Spring配置多个数据源,并实现数据源的动态切换转载)

    1.首先在config.properties文件中配置两个数据库连接的基本数据。这个省略了 
    2.在spring配置文件中配置这两个数据源: 
    数据源1

    <!-- initialSize初始化时建立物理连接的个数0  maxActive最大连接池数量8 minIdle最小连接池数量0-->
        <bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource" scope="singleton">
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <property name="url" value="${jdbc.url}" />
            <property name="initialSize" value="${jdbc.init}" />
            <property name="maxActive" value="${jdbc.max}" />
            <property name="minIdle" value="${jdbc.min}" />
        </bean>

    数据源2

    <bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource" scope="singleton">
            <property name="username" value="${jdbc.username2}" />
            <property name="password" value="${jdbc.password2}" />
            <property name="url" value="${jdbc.url2}" />
            <property name="initialSize" value="${jdbc.init2}" />
            <property name="maxActive" value="${jdbc.max2}" />
            <property name="minIdle" value="${jdbc.min2}" />
        </bean>

    3.自定义一个数据源类,该类继承 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource 
    并重写determineCurrentLookupKey()方法 
    3.1代码如下

    public class RoutingDataSource extends AbstractRoutingDataSource  {
    
         @Override
         protected Object determineCurrentLookupKey() {
                return DataSourceHolder.getDataSourceType();
         }
    
    }

     

    3.2将该类交由sping管理,其在spring配置文件中配置如下

    <bean id="dataSource" class="com.coe.exp.core.dataSource.RoutingDataSource">
            <!-- 为targetDataSources注入两个数据源 -->
            <property name="targetDataSources">
                <map key-type="java.lang.String">
                    <entry key="ds1" value-ref="dataSource1"/>
                    <entry key="ds2" value-ref="dataSource2"/>
                </map>
            </property>
            <!-- 为指定数据源RoutingDataSource注入默认的数据源-->
             <property name="defaultTargetDataSource" ref="dataSource1"/>
        </bean>

     

    3.3spring其他的配置如下

    <!-- MyBatis配置 -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 把dataSource注入给sqlSessionFactory -->
            <property name="dataSource" ref="dataSource" />
            <property name="typeAliasesPackage" value="com.coe.exp.core.ent" />
            <!-- 指定mapper.xml的位置 -->
            <property name="mapperLocations" >
                    <array>
                        <value>classpath:com/coe/exp/core/xml/**/*.xml</value>
                        <value>classpath:com/coe/exp/xml/**/*.xml</value>
                </array>
            </property>
            <!-- 指定myBatis配置文件的位置 -->
            <property name="configLocation" value="classpath:mybatis/sqlmapconfig.xml" />
        </bean>
    
    
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.coe.exp.core.mapper,com.coe.exp.mapper" />
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        </bean>
    
        <!-- 配置事务管理器 -->
        <bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
    
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
             <tx:attributes>
                 <tx:method name="insert*" propagation="REQUIRED"/>
                 <tx:method name="save*" propagation="REQUIRED"/>
                 <tx:method name="update*" propagation="REQUIRED"/>
                 <tx:method name="delete*" propagation="REQUIRED"/>
                 <tx:method name="remove*" propagation="REQUIRED"/>
                 <tx:method name="add*" propagation="REQUIRED"/>
                 <tx:method name="find*" propagation="SUPPORTS"/>
                 <tx:method name="get*" propagation="SUPPORTS"/>
             </tx:attributes>
         </tx:advice>
    
         <aop:config>
             <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.coe.exp.dao..*Impl.*(..))" order="2"/>
             <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.coe.exp.core.dao..*Impl.*(..))" order="3"/>
         </aop:config>
    
        <!-- 注解方式配置事物   -->
        <tx:annotation-driven transaction-manager="transactionManager" />
    
    <!-- 引入属性文件 -->
        <context:property-placeholder location="classpath:config.properties" />
        <!-- 自动扫描(自动注入) -->
        <context:component-scan base-package="com.coe.exp,mm" annotation-config="true">  
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
        <context:component-scan base-package="com.coe,mm"/>  
        <!-- 自动扫描定时任务 -->
        <task:annotation-driven/> 
        <!-- spring自动创建代理,植入切面,proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy  
        poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。 -->
        <aop:aspectj-autoproxy proxy-target-class="true"/>
        <import resource="../shiro/spring-shiro.xml"/>

    4.编写一个数据源持有类DataSourceHolder

    public class DataSourceHolder {
    
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); 
    
        /**
         * @Description: 设置数据源类型
         * @param dataSourceType  数据库类型
         * @return void
         * @throws
         */ 
        public static void setDataSourceType(String dataSourceType) { 
            contextHolder.set(dataSourceType); 
        } 
    
        /**
         * @Description: 获取数据源类型
         * @param 
         * @return String
         * @throws
         */ 
        public static String getDataSourceType() { 
            return contextHolder.get(); 
        } 
    
        /**
         * @Description: 清除数据源类型
         * @param 
         * @return void
         * @throws
         */ 
        public static void clearDataSourceType() { 
            contextHolder.remove(); 
        }
    }

    5.自定义注解

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import org.springframework.stereotype.Component;
    
    /**
     * 数据源
     * 
     * @author llb 2017-03-30
     *
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Component
    public @interface DataSource {
    
        String value() default "";
    
    }

    6.动态切换数据源

    import java.lang.reflect.Method;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Repository;
    
    import com.coe.exp.core.dataSource.DataSourceHolder;
    
    
    @Order(1)
    @Aspect  
    @Repository
    public class DataSourceAspect {
    
        @Pointcut("execution(* com..dao..*Impl.*(..))")
        private void anyMethod() {  
        }
    
        @AfterReturning(value = "anyMethod()", returning = "result")  
        public void afterReturning(JoinPoint joinPoint,Object result){
            DataSourceHolder.clearDataSourceType();
        }
    
        @Before(value="anyMethod()")
        public void before(JoinPoint joinPoint) throws Throwable {
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();  
            Method method = methodSignature.getMethod();  
            //如果方法体上使用了DataSource注解
            if (method.isAnnotationPresent(DataSource.class)) {
                //获取该方法上的注解名
                DataSource datasource = method.getAnnotation(DataSource.class);
                //将方法体上的注解的值赋予给DataSourceHolder数据源持有类
                DataSourceHolder.setDataSourceType(datasource.value());
            }
        }
    
    }

    7.若方法体上没有注解,则都是使用默认数据源,如果有以下注解,则使用指定的数据源

    /**
         * 查询哲盟数据库中所有状态正常的客户余额
         * @return
         * @author mxl
         * @version 2017年8月16日下午1:30:06
         */
        @DataSource("ds2")
        public List<CustomerBalanceEnt> getAllCustBalanceByZm(){
            return customerBalanceMapper.getAllCustBalanceByZm();
        }

     上面这个方法就是使用“ds2”;

    ---------------------
    作者:苹果树上的你
    来源:CSDN
    原文:https://blog.csdn.net/ll535299/article/details/78203634
    版权声明:本文为博主原创文章,转载请附上博文链接!

     

  • 相关阅读:
    Spinlock
    Leetcode: Summary Ranges
    Leetcode: Search a 2D Matrix
    Leetcode: Rotate Image
    Leetcode: Length of Last Word in python
    BBC-unit7 session1
    BBC-unit6 session5
    BBC-unit6 session4
    BBC英语-unit6 session3
    BBC英语-unit6 session2
  • 原文地址:https://www.cnblogs.com/nietzsche2019/p/11287748.html
Copyright © 2011-2022 走看看