• Spring+Hibernate框架下Mysql读写分离、主从数据库配置


    1. 配置AOP切面类 DataSourceAdvice.java

    package until;
    import java.lang.reflect.Method;
    import org.springframework.aop.AfterReturningAdvice;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.ThrowsAdvice;
    public class DataSourceAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {
    // service方法执行之前被调用
    public void before(Method method, Object[] args, Object target) throws Throwable {
    System.out.println("切入点: " + target.getClass().getName() + "类中" + method.getName() + "方法");
    if(method.getName().startsWith("add") 
    || method.getName().startsWith("create")
    || method.getName().startsWith("save")
    || method.getName().startsWith("edit")
    || method.getName().startsWith("update")
    || method.getName().startsWith("delete")
    || method.getName().startsWith("remove")){
    System.out.println("切换到: master");
    DataSourceSwitcher.setMaster();
    }
    else {
    System.out.println("切换到: slave");
    DataSourceSwitcher.setSlave();
    }
    }
    // service方法执行完之后被调用
    public void afterReturning(Object arg0, Method method, Object[] args, Object target) throws Throwable {
    }
    // 抛出Exception之后被调用
    public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
    DataSourceSwitcher.setSlave();
    System.out.println("出现异常,切换到: slave");
    }
    }
    2.数据源选择类 DataSourceSwitcher.java
    package until;
    import org.springframework.util.Assert;
    public class DataSourceSwitcher {
    @SuppressWarnings("rawtypes")
    private static final ThreadLocal contextHolder = new ThreadLocal();
    @SuppressWarnings("unchecked")
    public static void setDataSource(String dataSource) {
    Assert.notNull(dataSource, "dataSource cannot be null");
    contextHolder.set(dataSource);
    }
    public static void setMaster(){
    clearDataSource();
    }
    public static void setSlave() {
    setDataSource("slave");
    }
    public static String getDataSource() {
    return (String) contextHolder.get();
    }
    public static void clearDataSource() {
    contextHolder.remove();
    }
    }

    3. DynamicDataSource.java数据源动态切换类

    package until;
    import java.sql.SQLFeatureNotSupportedException;
    import java.util.logging.Logger;
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
    return DataSourceSwitcher.getDataSource();
    }
    }

    4. 下面配置spring applicationContext.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:context="http://www.springframework.org/schema/context" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-2.5.xsd 
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    
    <!-- dbcp数据源 -->
    <bean id="parentDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/readandwrite_test" />
    <property name="username" value="root" />
    <property name="password" value="root" />
    -->
    <property name="initialSize" value="10"/><!-- 初始化连接 -->
    <property name="maxIdle" value="50"/><!-- 最大空闲连接 -->
    <property name="minIdle" value="10"/><!-- 最小空闲连接 -->
    <property name="maxActive" value="300"/><!-- 最大连接数量 -->
    <property name="logAbandoned" value="true"/><!-- 是否在自动回收超时连接的时候打印连接的超时错误 -->
    <property name="removeAbandoned" value="true"/><!-- 是否自动回收超时连接 -->
    <property name="removeAbandonedTimeout" value="180"/><!-- 超时时间(以秒数为单位) -->
    <property name="maxWait" value="1000"/> <!--超时等待时间以毫秒为单位 -->
    
    <property name="testOnBorrow" value="false"/> <!-- 数据库连接池中取得连接时,对其的有效性进行检查 ,会影响一定性能-->
    <property name="testWhileIdle" value="true"/> <!--异步Evict的TimerTask定时线程进行控制 定时对线程池中的链接进行validateObject校验-->
    <property name="timeBetweenEvictionRunsMillis" value="25200000"/><!--失效检查线程运行时间间隔 大于0才会开启evict检查线程-->
    <property name="validationQuery" value="select 1"/> <!-- 校验sql-->
    </bean>
    <!-- 主数据源-->
    <bean id="masterDataSource" parent="parentDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/readandwrite_test" />
    <property name="username" value="root" />
    <property name="password" value="root" />
    </bean>
    <!-- 从数据源-->
    <bean id="slaveDataSource" parent="parentDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/readandwrite_test" />
    <property name="username" value="root" />
    <property name="password" value="root" />
    </bean>
    
    <!-- 数据源动态切换 -->
    <bean id="dataSource" class="until.DynamicDataSource">
    <property name="targetDataSources">
    <map key-type="java.lang.String">
    <entry key="slave" value-ref="slaveDataSource" />
    </map>
    </property>
    <property name="defaultTargetDataSource" ref="masterDataSource" />
    </bean>
    
    <!-- 配置sessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="mappingResources">
    <list>
    <value>hbm/User.hbm.xml</value>
    </list>
    </property>
    <property name="hibernateProperties">
    <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    <prop key="hibernate.show_sql">true</prop> 
    </props>
    </property>
    </bean>
    
    <!-- 切换数据源 -->
    <bean id="dataSourceAdvice" class="until.DataSourceAdvice" />
    <aop:config>
    <aop:advisor
    pointcut="execution(* service..*Service.*(..))"
    advice-ref="dataSourceAdvice" />
    </aop:config>
    
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
    <ref bean="sessionFactory" />
    </property>
    </bean>
    <!--配置事务的传播特性 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <!-- 对增、删、改方法进行事务支持 -->
    <tx:method name="add*" propagation="REQUIRED" />
    <tx:method name="create*" propagation="REQUIRED" />
    <tx:method name="save*" propagation="REQUIRED" />
    <tx:method name="edit*" propagation="REQUIRED" />
    <tx:method name="update*" propagation="REQUIRED" />
    <tx:method name="delete*" propagation="REQUIRED" />
    <tx:method name="remove*" propagation="REQUIRED" />
    <!-- 对查找方法进行只读事务 -->
    <tx:method name="load*" propagation="SUPPORTS" read-only="true" />
    <!-- 对其它方法进行只读事务 -->
    <tx:method name="*" propagation="SUPPORTS" read-only="true" />
    </tx:attributes>
    </tx:advice>
    <!--那些类的哪些方法参与事务 -->
    <aop:config>
    <aop:advisor
    pointcut="execution(* service..*Service.*(..))"
    advice-ref="txAdvice" />
    <aop:advisor
    pointcut="execution(* service..*ServiceImpl.*(..))"
    advice-ref="txAdvice" />
    </aop:config>
    </beans>
  • 相关阅读:
    HDU 4024 Dwarven Sniper’s hunting(数学公式 或者是二分)
    二分图最大匹配总结
    HDU 4022 Bombing (STL应用)
    HDU 1847 Good Luck in CET4 Everybody!(组合博弈)
    HDU 1556 Color the ball(树状数组)
    HDU 4023 Game(博弈)
    HDU 1406 完数(水题)
    HDU 4021 24 Puzzle
    Oracle 多表查询优化
    【编程之美】字符串移位包含的问题(续)
  • 原文地址:https://www.cnblogs.com/tongxinyuan/p/4435425.html
Copyright © 2020-2023  润新知