《Spring4+Hibernate4+proxool配置多数据源实现读写分离》
我在写一个Spring4+Hibernate4+proxool配置多数据源实现读写分离的demo。但切换不了数据库,请高手指教一下。下面是我的代码:
1、数据库的一个配置
driverClassName=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@192.168.0.41:1521:orcl
username=amb
password=amb
driverName=oracle.jdbc.driver.OracleDriver
dataUrl=jdbc:oracle:thin:@192.168.0.16:1521:orcl
userName=test
passWord=test
hibernateDialect=org.hibernate.dialect.Oracle9Dialect
hibernateShowSQL=true
二、这是关于线程池以及多数据源的配置
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 使用Spring的Annotation的配置 -->
<context:annotation-config />
<!-- 除了Controller,Bean全部自动到包里面找 -->
<context:component-scan base-package="ecen.tenement">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- 开启占位符来配置Properties文件的值 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:ecen/tenement/config/jdbc.properties</value>
</property>
</bean>
<!-- 使用Proxool来配置JDBC -->
<bean id="proxoolDataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
<property name="alias">
<value>tenement</value>
</property>
<property name="driver">
<value>${driverClassName}</value>
</property>
<property name="driverUrl">
<value>${url}</value>
</property>
<property name="user">
<value>${username}</value>
</property>
<property name="password">
<value>${password}</value>
</property>
<!-- 最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候 -->
<property name="maximumConnectionCount">
<value>20</value>
</property>
<!-- 最小连接数(默认2个) -->
<property name="minimumConnectionCount">
<value>3</value>
</property>
<!-- 最少保持的空闲连接数(默认2个) -->
<property name="prototypeCount">
<value>3</value>
</property>
<!-- 是否记录数据库的每一步操作 -->
<property name="trace">
<value>true</value>
</property>
<!-- 是否同时记录多个STUFF,会产生多个日志 -->
<property name="verbose">
<value>true</value>
</property>
<!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒 -->
<property name="houseKeepingSleepTime">
<value>90000</value>
</property>
<!-- 保持数据库连接所使用的SQL语句 -->
<property name="houseKeepingTestSql">
<value>SELECT CURRENT_DATE</value>
</property>
</bean>
<!-- 使用Proxool来配置JDBC -->
<bean id="proxoolDataSourceTest" class="org.logicalcobwebs.proxool.ProxoolDataSource">
<property name="alias">
<value>tenement</value>
</property>
<property name="driver">
<value>${driverName}</value>
</property>
<property name="driverUrl">
<value>${dataUrl}</value>
</property>
<property name="user">
<value>${userName}</value>
</property>
<property name="password">
<value>${passWord}</value>
</property>
<!-- 最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候 -->
<property name="maximumConnectionCount">
<value>30</value>
</property>
<!-- 最小连接数(默认2个) -->
<property name="minimumConnectionCount">
<value>3</value>
</property>
<!-- 最少保持的空闲连接数(默认2个) -->
<property name="prototypeCount">
<value>3</value>
</property>
<!-- 是否记录数据库的每一步操作 -->
<property name="trace">
<value>true</value>
</property>
<!-- 是否同时记录多个STUFF,会产生多个日志 -->
<property name="verbose">
<value>true</value>
</property>
<!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒 -->
<property name="houseKeepingSleepTime">
<value>90000</value>
</property>
<!-- 保持数据库连接所使用的SQL语句 -->
<property name="houseKeepingTestSql">
<value>SELECT CURRENT_DATE</value>
</property>
</bean>
<bean id="dynamicDataSource" class="ecen.tenement.datasource.DynamicDataSource">
<!-- 通过key-value的形式来关联数据源 -->
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="proxoolDataSource" key="dataSourceA"></entry>
<entry value-ref="proxoolDataSourceTest" key="dataSourceB"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="proxoolDataSource">
</property>
</bean>
<!-- 支持 @AspectJ 标记-->
<aop:aspectj-autoproxy />
<bean class="ecen.tenement.datasource.DynamicDataSourceAspect" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dynamicDataSource" />
<!-- 直接扫描这个包里面的Entity类,建议使用 -->
<property name="packagesToScan">
<list>
<value>ecen.tenement.model</value>
</list>
</property>
<!-- Hibernate配置中的各种属性,具体请查询HinbernateDOC文档 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernateDialect}</prop>
<prop key="hibernate.show_sql">${hibernateShowSQL}</prop>
<!-- 是否使用CGLIB动态代理对象(小而快,推荐,需要CGLIB包,建议配合Proxool使用) -->
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
<!-- 指定Hibernate在何时释放JDBC连接 -->
<prop key="hibernate.connection.release_mode">auto</prop>
<prop key="hibernate.hbm2ddl.auto"></prop>
</props>
</property>
</bean>
<!-- 使用Hibernate模板,极大简化Hibernate的开发 -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 自动Hibernate事务处理,自动Rollback,自动TryCatch -->
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<!-- 把SessionFactory注给Tx -->
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置事务管理 -->
<tx:annotation-driven transaction-manager="txManager" />
<!-- 配置Transcation 自动处理,属于切面编程 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="load*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
</beans> 三、我切换数据库的实现
package ecen.tenement.datasource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 设置数据源
* @author 檀溪
*
*/
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
String string = CustomerContextHolder.getCustomerType();
return string;
}
}
package ecen.tenement.datasource;
/**
* 控制数据源的类
* @author 檀溪
*
*/
public class CustomerContextHolder {
public static final String DATA_SOURCE_A = "dataSourceA";
public static final String DATA_SOURCE_B = "dataSourceB";
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setCustomerType(String customerType) {
contextHolder.set(customerType);
}
public static String getCustomerType() {
return contextHolder.get();
}
public static void clearCustomerType() {
contextHolder.remove();
}
}
package ecen.tenement.datasource;
import java.io.IOException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
* 使用AOP切面来切换数据源
* @author 檀溪
*
*/
@Aspect
public class DynamicDataSourceAspect {
//execution (* ecen.tenement.service.*.*.*(..))
public void serviceExecution(){}
@Before("execution (* ecen.tenement.service.*.*.*(..))")
public void getUser(JoinPoint jp) throws IOException {
CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_B);
System.out.println("切换数据源");
}
}
方法每次都执行了,但是就是切换不了数据源,程序也没有出现任何异常