《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("切换数据源"); } }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于determineCurrentLookupKey 方法优先于切入方法 getUser,所以切换不了数据源