MyException - 我的异常网
当前位置:我的异常网» 行业应用 » 透过识别方法注解,自动切换主备数据源DynamicDataS

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

www.MyException.Cn  网友分享于:2013-03-06  浏览:0次
通过识别方法注解,自动切换主备数据源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

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

文章评论

不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
编程语言是女人
编程语言是女人
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员应该关注的一些事儿
程序员应该关注的一些事儿
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
 程序员的样子
程序员的样子
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
旅行,写作,编程
旅行,写作,编程
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
程序员必看的十大电影
程序员必看的十大电影
那些争议最大的编程观点
那些争议最大的编程观点
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
鲜为人知的编程真相
鲜为人知的编程真相
10个调试和排错的小建议
10个调试和排错的小建议
总结2014中国互联网十大段子
总结2014中国互联网十大段子
我是如何打败拖延症的
我是如何打败拖延症的
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
程序员的鄙视链
程序员的鄙视链
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
一个程序员的时间管理
一个程序员的时间管理
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
我的丈夫是个程序员
我的丈夫是个程序员
每天工作4小时的程序员
每天工作4小时的程序员
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
程序员都该阅读的书
程序员都该阅读的书
老程序员的下场
老程序员的下场
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
代码女神横空出世
代码女神横空出世
Java程序员必看电影
Java程序员必看电影
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
如何成为一名黑客
如何成为一名黑客
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
程序员和编码员之间的区别
程序员和编码员之间的区别
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
为什么程序员都是夜猫子
为什么程序员都是夜猫子
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有