前言
本来只是动态数据源切换的话,是不准备记录下来当博客发表的。但是在使用Spring + Hibernate实现数据源切换时,遇到了切换失败的问题。无论是查看源码还是debug调试都解决不了,最后还是在网上找到了答案,这里留一个悬念。
所以本文主旨在查阅大量资料后解决动态切换数据源失败的问题,顺便在前面介绍如何进行配置动态切换数据源。所有场景以Spring 4.2.6 + Hibernate 4.2.7 + proxool为标准,后文不再赘述。
正文
设计思路
Hibernate所有事务的操作都是和session绑定,而session由sessionFactory生成。sessionFactory作为一个重量级别的对象,不宜根据数据源的不同生成多个sessionFactory对象。这也是使用单例的原因。那么想动态切换数据源只能从sessionFactory依赖的dataSource动手。而Spring从2.0版本就提供了一个可以动态切换的数据源AbstractRoutingDataSource,那么所有的一切就有了解决方案:
设计实现
Spring关于数据源事务管理器的配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <bean id="parentDataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource"> <property name="user" value="${jdbc.username}"/> <property name="driver" value="${jdbc.driverClassName}"/> <property name="maximumConnectionCount" value="1000"/> <property name="minimumConnectionCount" value="20"/> <property name="houseKeepingSleepTime" value="300000"/><!-- 自动侦查各个连接状态的时间间隔,空闲的回收,超时的销毁,单位毫秒 --> <property name="simultaneousBuildThrottle" value="200"/> <property name="prototypeCount" value="5"/> <property name="maximumActiveTime" value="172800000"/> <property name="maximumConnectionLifetime" value="180000000"/> <property name="testBeforeUse" value="false"/> <property name="houseKeepingTestSql" value="select CURRENT_DATE"/> </bean> <bean parent="parentDataSource" id="production_env"> <property name="driverUrl" value="${jdbc.url.local}"/> <property name="password" value="${jdbc.password.local}"/> <property name="alias" value="proxool.a2"/> </bean> <bean parent="parentDataSource" id="test_env"> <property name="driverUrl" value="${jdbc.url.server.test}"/> <property name="password" value="${jdbc.password.server.test}"/> <property name="alias" value="proxool.a1"/> </bean> <bean class="com.config.datasource.DynamicDataSource" id&#