读写分离

  上一篇写了多表映射,就一口气写完读写分离吧

   原理跟多表映射的差不多。

   配置读写分离是为了在数据大时读库跟写库分离开来,以加快系统响应速度,减轻数据库压力。

  读写原理就是配置多数据源,在调用service层时用spring的aop把方法都拦下来,然后根据方法名称如find开头,get开头这样的就设置读数据源,其它就设置写数据源。

    在注入dao层时的sessionFactory就要给sessionFactory注入路由数据源,而不是具体一个数据源了,这样才可以动态的设置数据源。

     主要就是这个路由数据源DynamicDataSource继承AbstractRoutingDataSource,重写码               determineCurrentLookupKey,动态lookup数据源

 

   上代码吧:

    数据源选择类

  

Java代码   收藏代码
  1.    
  2. /** 
  3.  * 数据源选择类 
  4.  * @author miraclerz 
  5.  */  
  6. import org.springframework.util.Assert;  
  7.   
  8. public class DataSourceSwitcher {  
  9.     @SuppressWarnings("rawtypes")  
  10.     private static final ThreadLocal contextHolder = new ThreadLocal();  
  11.   
  12.     @SuppressWarnings("unchecked")  
  13.     public static void setDataSource(String dataSource) {  
  14.         Assert.notNull(dataSource, "dataSource cannot be null");  
  15.         contextHolder.set(dataSource);  
  16.     }  
  17.   
  18.     public static void setMaster(){  
  19.         clearDataSource();  
  20.        // setDataSource("master");  
  21.     }  
  22.   
  23.     public static void setSlave() {  
  24.         setDataSource("slave");  
  25.     }  
  26.   
  27.     public static String getDataSource() {  
  28.   
  29.         return (String) contextHolder.get();  
  30.     }  
  31.   
  32.     public static void clearDataSource() {  
  33.         contextHolder.remove();  
  34.     }  
  35. }  

 

数据源动态切换类

Java代码   收藏代码
  1.    
  2. /** 
  3.  * 数据源动态切换类 
  4.  * @author miraclerz 
  5.  */  
  6. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;  
  7.   
  8. public class DynamicDataSource extends AbstractRoutingDataSource {  
  9.   
  10.     @Override  
  11.     protected Object determineCurrentLookupKey() {  
  12.         /*System.out.println("dataSource:"+DataSourceSwitcher.getDataSource());*/  
  13.         return DataSourceSwitcher.getDataSource();  
  14.     }  
  15.   
  16. }  

 AOP切面类

Java代码   收藏代码
  1.    
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import org.springframework.aop.AfterReturningAdvice;  
  6. import org.springframework.aop.MethodBeforeAdvice;  
  7. import org.springframework.aop.ThrowsAdvice;  
  8.   
  9. import sy.datasource.DataSourceSwitcher;  
  10. /** 
  11.  * AOP切面类 
  12.  * @author miraclerz 
  13.  */  
  14. public class DataSourceAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {  
  15.     // service方法执行之前被调用  
  16.     public void before(Method method, Object[] args, Object target) throws Throwable {  
  17.         System.out.println("切入点: " + target.getClass().getName() + "类中" + method.getName() + "方法");  
  18.         if(method.getName().startsWith("get")  
  19.             || method.getName().startsWith("find")  
  20.             || method.getName().startsWith("count")){  
  21.             /*  System.out.println("切换到读: slave");*/  
  22.               DataSourceSwitcher.setSlave();  
  23.         }  
  24.         else  {  
  25.         /*   System.out.println("切换到主写: master");*/  
  26.              DataSourceSwitcher.setMaster();  
  27.   
  28.         }  
  29.         System.out.println("使用数据库:"+DataSourceSwitcher.getDataSource());  
  30.     }  
  31.   
  32.     // service方法执行完之后被调用  
  33.     public void afterReturning(Object arg0, Method method, Object[] args, Object target) throws Throwable {  
  34.     }  
  35.   
  36.     // 抛出Exception之后被调用  
  37.     public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {  
  38.         DataSourceSwitcher.setMaster();  
  39.         System.out.println("出现异常,切换到: master");  
  40.     }  
  41.   
  42. }  

 配置文件:

Java代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:c="http://www.springframework.org/schema/c" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"  
  3.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
  4.         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd  
  5.         http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd  
  6.         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd  
  7.         http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd  
  8.         http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd  
  9.         http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd  
  10.         http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd  
  11.         http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd  
  12.         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd  
  13.         http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">  
  14.   
  15.  <!--读写分离配置  -->  
  16.   
  17.     <!-- 加载properties配置文件 -->  
  18.   <!--   <bean id="propertyConfigurer"  
  19.         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  20.         <property name="locations">  
  21.             <list>  
  22.                 <value>classpath:readWrite/jdbc.properties</value>  
  23.             </list>  
  24.         </property>  
  25.     </bean> -->  
  26.    <bean id="parentDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">  
  27.             <property name="driverClassName" value="${master.jdbc.driverClassName}" />  
  28.             <property name="url" value="${master.jdbc.url}" />  
  29.             <property name="username" value="${master.jdbc.username}" />  
  30.             <property name="password" value="${master.jdbc.password}" />  
  31.             <!-- 初始化连接大小 -->  
  32.             <property name="initialSize" value="0" />  
  33.             <!-- 连接池最大使用连接数量 -->  
  34.             <property name="maxActive" value="20" />  
  35.             <!-- 连接池最小空闲 -->  
  36.             <property name="minIdle" value="0" />  
  37.             <!-- 获取连接最大等待时间 -->  
  38.             <property name="maxWait" value="60000" />  
  39.             <property name="testOnBorrow" value="false" />  
  40.             <property name="testOnReturn" value="false" />  
  41.             <property name="testWhileIdle" value="true" />  
  42.   
  43.             <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->  
  44.             <property name="timeBetweenEvictionRunsMillis" value="60000" />  
  45.             <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->  
  46.             <property name="minEvictableIdleTimeMillis" value="25200000" />  
  47.   
  48.             <!-- 打开removeAbandoned功能 -->  
  49.             <property name="removeAbandoned" value="true" />  
  50.             <!-- 1800秒,也就是30分钟 -->  
  51.             <property name="removeAbandonedTimeout" value="1800" />  
  52.             <!-- 关闭abanded连接时输出错误日志 -->  
  53.             <property name="logAbandoned" value="true" />  
  54.   
  55.             <!-- 监控数据库 -->  
  56.             <!-- <property name="filters" value="mergeStat" /> -->  
  57.             <property name="filters" value="stat" />  
  58.     </bean>  
  59.      <!-- 主数据源 -->  
  60.     <bean id="masterDataSource" parent="parentDataSource">  
  61.         <property name="driverClassName" value="${master.jdbc.driverClassName}" />  
  62.         <property name="url" value="${master.jdbc.url}" />  
  63.         <property name="username" value="${master.jdbc.username}" />  
  64.         <property name="password" value="${master.jdbc.password}" />  
  65.         <property name="validationQuery" value="${master.hibernate.validationQuery}" />  
  66.   
  67.     </bean>  
  68.     <!-- 从数据源 读-->  
  69.     <bean id="slaveDataSource" parent="parentDataSource">  
  70.         <property name="driverClassName" value="${slave.jdbc.driverClassName}" />  
  71.         <property name="url" value="${slave.jdbc.url}" />  
  72.         <property name="username" value="${slave.jdbc.username}" />  
  73.         <property name="password" value="${slave.jdbc.password}" />  
  74.         <property name="validationQuery" value="${slave.hibernate.validationQuery}" />  
  75.   
  76.   
  77.     </bean>  
  78. <!--dynamicDataSource 是用的数据源,包括了读写数据源  -->  
  79.     <bean id="dynamicDataSource" class="sy.datasource.DynamicDataSource">  
  80.         <property name="targetDataSources">  
  81.             <map key-type="java.lang.String">  
  82.                <entry key="master" value-ref="masterDataSource" />  
  83.                 <entry key="slave" value-ref="slaveDataSource" />  
  84.             </map>  
  85.         </property>  
  86.         <property name="defaultTargetDataSource" ref="masterDataSource" />  
  87.     </bean>  
  88.   
  89.     <!-- 配置sessionFactory -->  
  90.     <bean id="sessionFactory"  
  91.        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">  
  92.         <property name="dataSource" ref="dynamicDataSource"></property>  
  93.          <property name="hibernateProperties">  
  94.             <props>  
  95.                 <prop key="hibernate.hbm2ddl.auto">${read_write_hibernate.hbm2ddl.auto}</prop>  
  96.                 <prop key="hibernate.dialect">${read_write_hibernate.dialect}</prop>  
  97.                 <prop key="hibernate.show_sql">${read_write_hibernate.show_sql}</prop>  
  98.                 <prop key="hibernate.format_sql">${read_write_hibernate.format_sql}</prop>  
  99.                 <prop key="hibernate.use_sql_comments">${read_write_hibernate.use_sql_comments}</prop>  
  100.             </props>  
  101.         </property>  
  102.        <!-- 自动扫描注解方式配置的hibernate类文件 -->  
  103.         <property name="packagesToScan">  
  104.             <list>  
  105.                 <value>sy.model.base</value>  
  106.             </list>  
  107.         </property>  
  108.   
  109.     </bean>  
  110.   
  111.     <!-- 切换数据源 -->  
  112.     <bean id="dataSourceAdvice" class="sy.aop.DataSourceAdvice" />  
  113.     <aop:config>  
  114.         <aop:advisor  
  115.             pointcut="(execution(* sy.service.base..*Impl.*(..)))"  
  116.             advice-ref="dataSourceAdvice" />  
  117.     </aop:config>  
  118.   
  119.     <!-- 配置事务管理器 -->  
  120.     <bean id="read_write_transactionManager"  
  121.          class="org.springframework.orm.hibernate4.HibernateTransactionManager">  
  122.        <property name="sessionFactory" ref="sessionFactory"></property>  
  123.   
  124.     </bean>  
  125.   
  126.   
  127.   
  128.   
  129. <!-- 拦截器方式配置事物 -->  
  130.     <tx:advice id="read_write_txAdvice" transaction-manager="read_write_transactionManager">  
  131.         <tx:attributes>  
  132.             <tx:method name="save*" propagation="REQUIRED" />  
  133.             <tx:method name="update*" propagation="REQUIRED" />  
  134.             <tx:method name="saveOrUpdate*" propagation="REQUIRED" />  
  135.             <tx:method name="delete*" propagation="REQUIRED" />  
  136.             <tx:method name="grant*" propagation="REQUIRED" />  
  137.   
  138.             <tx:method name="init*" propagation="REQUIRED" />  
  139.   
  140.             <tx:method name="*" propagation="REQUIRED" read-only="true" />  
  141.         </tx:attributes>  
  142.     </tx:advice>  
  143.     <aop:config>  
  144.         <!-- 第一个*代表所有的返回值类型;第二个*代表所有的类;第三个*代表类所有方法;..代表子或者孙子包;最后一个..代表所有的参数 -->  
  145.         <aop:pointcut id="read_write_transactionPointcut" expression="(execution(* sy.service.base..*Impl.*(..)))" />  
  146.         <aop:advisor pointcut-ref="read_write_transactionPointcut" advice-ref="read_write_txAdvice" />  
  147.   
  148.   
  149.     </aop:config>  
  150.   
  151. </beans>  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值