通过识别方法注解,自动切换主备数据源DynamicDataSource

 

 

org.springframework.jdbc.datasource.lookup,数据库主备配置

 

mysql.properties:

 

crm.jdbc.driverClassName=com.mysql.jdbc.Driver 

crm.jdbc.url=jdbc:mysql://10.100.163.77:3306/financial_sales_prod?useUnicode=true&characterEncoding=utf-8

crm.jdbc.username=telsale/-pl

crm.jdbc.password=0OKM

crm.dbcp.initialSize=5

扫描二维码关注公众号,回复: 203748 查看本文章

crm.dbcp.minIdle=5

crm.dbcp.maxActive=20

crm.dbcp.maxWait=10000

crm.dbcp.timeBetweenEvictionRunsMillis=60000

crm.dbcp.minEvictableIdleTimeMillis=300000

crm.dbcp.testWhileIdle=true

crm.dbcp.testOnBorrow=true

crm.dbcp.testOnReturn=false

crm.dbcp.poolPreparedStatements=true

crm.dbcp.maxPoolPreparedStatementPerConnectionSize=20

 

bigdata.jdbc.driverClassName=com.mysql.jdbc.Driver 

bigdata.jdbc.url=jdbc:mysql://10.100.163.78:3306/financial_sales_prod?useUnicode=true&characterEncoding=utf-8

bigdata.jdbc.username=telsale/-pl

bigdata.jdbc.password=0OKM

bigdata.dbcp.initialSize=5

bigdata.dbcp.minIdle=5

bigdata.dbcp.maxActive=20

bigdata.dbcp.maxWait=10000

bigdata.dbcp.timeBetweenEvictionRunsMillis=60000

bigdata.dbcp.minEvictableIdleTimeMillis=300000

bigdata.dbcp.testWhileIdle=true

bigdata.dbcp.testOnBorrow=true

bigdata.dbcp.testOnReturn=false

bigdata.dbcp.poolPreparedStatements=true

bigdata.dbcp.maxPoolPreparedStatementPerConnectionSize=20

 

 

 

 

 

 

 

 

applicationContext-dao.xml:

 

 

 

 

 

<?xml version="1.0" encoding="UTF-8"?>

 

<!--suppress ALL -->

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:tx="http://www.springframework.org/schema/tx"

       xmlns:aop="http://www.springframework.org/schema/aop"

       xmlns="http://www.springframework.org/schema/beans"

       xsi:schemaLocation="

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

 

    <bean id="crm_dataSource" class="com.alibaba.druid.pool.DruidDataSource"

          init-method="init" destroy-method="close">

        <property name="driverClassName" value="${crm.jdbc.driverClassName}"/>

        <property name="url" value="${crm.jdbc.url}"/>

        <property name="username" value="${crm.jdbc.username}"/>

        <property name="password" value="${crm.jdbc.password}"/>

 

        <!-- 配置初始化大小、最小、最大 -->

        <property name="initialSize" value="${crm.dbcp.initialSize}"/>

        <property name="minIdle" value="${crm.dbcp.minIdle}"/>

        <property name="maxActive" value="${crm.dbcp.maxActive}"/>

 

        <!-- 配置获取连接等待超时的时间 -->

        <property name="maxWait" value="${crm.dbcp.maxWait}"/>

 

        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->

        <property name="timeBetweenEvictionRunsMillis" value="${crm.dbcp.timeBetweenEvictionRunsMillis}"/>

 

        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->

        <property name="minEvictableIdleTimeMillis" value="${crm.dbcp.minEvictableIdleTimeMillis}"/>

 

        <property name="testWhileIdle" value="${crm.dbcp.testWhileIdle}"/>

 

        <!-- 防止取到的连接不可用, 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能-->

        <property name="testOnBorrow" value="${crm.dbcp.testOnBorrow}"/>

        <!-- 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 -->

        <property name="testOnReturn" value="${crm.dbcp.testOnReturn}"/>

 

        <!-- 打开PSCache,并且指定每个连接上PSCache的大小 在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。5.5及以上版本有PSCache,建议开启-->

        <property name="poolPreparedStatements" value="${crm.dbcp.poolPreparedStatements}"/>

        <property name="maxPoolPreparedStatementPerConnectionSize"

                  value="${crm.dbcp.maxPoolPreparedStatementPerConnectionSize}"/>

 

        <!-- 这里配置提交方式,默认就是TRUE,可以不用配置 -->

        <property name="defaultAutoCommit" value="true"/>

 

        <!-- 验证连接有效与否的SQL,不同的数据库配置不同 -->

        <property name="validationQuery" value="select 1 "/>

        <!-- 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall-->

        <property name="filters" value="stat"/>

       <!--  <property name="proxyFilters">

            <list>

                <ref bean="logFilter"/>

            </list>

        </property> -->

    </bean>

 

    <bean id="bigdata_dataSource" class="com.alibaba.druid.pool.DruidDataSource"

          init-method="init" destroy-method="close">

        <property name="driverClassName" value="${bigdata.jdbc.driverClassName}"/>

        <property name="url" value="${bigdata.jdbc.url}"/>

        <property name="username" value="${bigdata.jdbc.username}"/>

        <property name="password" value="${bigdata.jdbc.password}"/>

 

        <!-- 配置初始化大小、最小、最大 -->

        <property name="initialSize" value="${bigdata.dbcp.initialSize}"/>

        <property name="minIdle" value="${bigdata.dbcp.minIdle}"/>

        <property name="maxActive" value="${bigdata.dbcp.maxActive}"/>

 

        <!-- 配置获取连接等待超时的时间 -->

        <property name="maxWait" value="${bigdata.dbcp.maxWait}"/>

 

        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->

        <property name="timeBetweenEvictionRunsMillis" value="${bigdata.dbcp.timeBetweenEvictionRunsMillis}"/>

 

        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->

        <property name="minEvictableIdleTimeMillis" value="${bigdata.dbcp.minEvictableIdleTimeMillis}"/>

 

        <property name="testWhileIdle" value="${bigdata.dbcp.testWhileIdle}"/>

 

        <!-- 防止取到的连接不可用, 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能-->

        <property name="testOnBorrow" value="${bigdata.dbcp.testOnBorrow}"/>

        <!-- 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 -->

        <property name="testOnReturn" value="${bigdata.dbcp.testOnReturn}"/>

 

        <!-- 打开PSCache,并且指定每个连接上PSCache的大小 在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。5.5及以上版本有PSCache,建议开启-->

        <property name="poolPreparedStatements" value="${bigdata.dbcp.poolPreparedStatements}"/>

        <property name="maxPoolPreparedStatementPerConnectionSize"

                  value="${bigdata.dbcp.maxPoolPreparedStatementPerConnectionSize}"/>

 

        <!-- 这里配置提交方式,默认就是TRUE,可以不用配置 -->

        <property name="defaultAutoCommit" value="true"/>

 

        <!-- 验证连接有效与否的SQL,不同的数据库配置不同 -->

        <property name="validationQuery" value="select 1 "/>

        <!-- 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall-->

        <property name="filters" value="stat"/>

        <property name="proxyFilters">

            <list>

                <ref bean="logFilter"/>

            </list>

        </property>

    </bean>

 

    <bean id="logFilter" class="com.alibaba.druid.filter.logging.Slf4jLogFilter">

        <property name="statementExecutableSqlLogEnable" value="false"/>

        <property name="resultSetLogEnabled" value="false"/>

        

        

    </bean>

 

    <bean id="dynamicDataSource"  class="com.houbank.incoming.dao.datasource.DynamicDataSource" >

        <property name="targetDataSources" >

            <map>

                <entry key="crm_dataSource" value-ref="crm_dataSource" />    //两个数据源

                <entry key="bigdata_dataSource" value-ref="bigdata_dataSource" />

            </map>

        </property>

        <property name="defaultTargetDataSource"  ref="crm_dataSource" />  //主库

    </bean>

 

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

        <property name="dataSource" ref="dynamicDataSource"/>

        <property name="mapperLocations">

            <array>

                <value>classpath*:mapper/*.xml</value>

                <value>classpath*:WorkProcessorMapper/*.xml</value>

            </array>

        </property>

        <property name="configLocation" value="classpath:/META-INF/spring/mybatis-configuration.xml"/>

    </bean>

 

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

        <property name="basePackage" value="com.houbank.incoming.dao.mapper"/>

        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>

    </bean>

 

   

 

    <!--动态数据源切面配置-->

    <bean id="dataSourceAspect" class="com.houbank.incoming.dao.datasource.DynamicDataSourceAspect" />  //切面配置

 

    <!-- 事务配置开始 -->

    <bean id="transactionManager"

          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

        <property name="dataSource" ref="dynamicDataSource"/>

    </bean>

    <tx:annotation-driven/>

    <!--对于方法的细粒度事务配置,符合条件的方法冠以相应的事务-->

    <tx:advice id="txAdvice" transaction-manager="transactionManager">

        <tx:attributes>

            <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>

            <tx:method name="remove*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>

            <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>

            <tx:method name="add*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>

            <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>

            <tx:method name="save*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>

            <tx:method name="submit*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>

            <tx:method name="newTrans*" propagation="REQUIRES_NEW" read-only="false"

                       rollback-for="java.lang.Exception"/>

            <tx:method name="modify*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>

            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>

            <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>

            <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>

            <tx:method name="query*" propagation="SUPPORTS" read-only="true"/>

        </tx:attributes>

    </tx:advice>

    <!--把事务控制在Service层 -->

    <aop:config>

        <!--这里配置规则,满足以下规则的将触发事务,第一个*表示所有返回类型,第二个表示service包下的所有class,第三个表示所有方法-->

        <aop:pointcut id="servicePointCut"

                      expression="execution(public * com.houbank.incoming.service.*.*(..))"/>

        <aop:advisor pointcut-ref="servicePointCut" advice-ref="txAdvice"/>

        <!-- 将切面应用到自定义的切面处理器上,-9999保证该切面优先级最高执行 -->

        <aop:advisor advice-ref="dataSourceAspect" pointcut-ref="servicePointCut" order="1" />

    </aop:config>

    <!-- 事务配置结束 -->

</beans>

 

 

 

 

 

 

 

java:

 

 

自定义数据源:

 

package com.houbank.incoming.dao.datasource;

 

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

 

import javax.sql.DataSource;

 

/**

 * Created by xiaogaoxu on 2016/8/25.

 */

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override

    protected Object determineCurrentLookupKey() {

        return DatasourceHold.getDBType();

    }

 

    @Override

    public DataSource determineTargetDataSource() {

        return super.determineTargetDataSource();

    }

}

 

 

 

自定义数据源切面:

 

package com.houbank.incoming.dao.datasource;

 

import java.lang.reflect.Method;

 

import org.springframework.aop.AfterReturningAdvice;

import org.springframework.aop.MethodBeforeAdvice;

 

/**

 * Created by xiaogaoxu on 2016/8/25.

 */

public class DynamicDataSourceAspect implements MethodBeforeAdvice, AfterReturningAdvice {

 

    @Override

    public void afterReturning(Object returnValue, Method method,

                               Object[] args, Object target) throws Throwable {

        DatasourceHold.clearDBType();

    }

 

    @Override

    public void before(Method method, Object[] args, Object target)

            throws Throwable {

 

        if (method.isAnnotationPresent(DataSource.class)) {     //这里通过方法的注解区分哪些方式使用哪种数据库,大数据查询的专门使用查询的库

            DataSource datasource = method.getAnnotation(DataSource.class);

            DatasourceHold.setDBType(datasource.name());

        } else {

            DatasourceHold.clearDBType();

        }

 

    }

}

 

 

 

 

package com.houbank.incoming.dao.datasource;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface DataSource {

    /**

     * CRM系统的主数据源 系统默认

     */

    String CRM_DATASOURCE = "crm_dataSource";

    /**

     * 大数据的数据源 只读同步数据

     */

    String BIGDATA_DATASOURCE = "bigdata_dataSource";

    String name();

}

 

 

 mybatis采用的是多数据源配置

crm_dataSource CRM系统的主数据源
bigdata_dataSource 大数据的数据源 只读同步数据

示例:
@DataSource(name = DataSource.BIGDATA_DATASOURCE)
   public List<TagFilterRel> selectByCondition(TagFilterRel rel) {
           return tagFilterRelMapper.selectByCondition(rel);
       }

mybatis数据源及事务配置见applicationContext-dao.xml

猜你喜欢

转载自yuhuiblog6338999322098842.iteye.com/blog/2409003