spring+hibernate动态切换数据源

动态切换数据源确切的来说是在同一类型数据库的情况下的。意思就是说 , 在系统中的使用的数据库分布在多台数据库服务器或者在同台服务器上的多个数据库. 在运行时期间根据某种标识符来动态的选择当前操作的数据库.

  1. 数据源是相同类型的数据库: 一个SessionFactory+动态数据源+一个事务管理器
  2. 数据源是不同类型的数据库: 根据类型 配置多套SessionFactory

spring配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="transactionInterceptor"
          class="org.springframework.transaction.interceptor.TransactionInterceptor">
         <property name="transactionManager" ref="transactionManager"/>
         <property name="transactionAttributes">
        <!--  如果还有其他的发放类型需要进行事务的统一处理,请修改此处的key值和事务等级  -->
        <props>
             <prop key="insert*">PROPAGATION_REQUIRES_NEW</prop>            
             <prop key="save*">PROPAGATION_REQUIRED</prop>
             <prop key="add*">PROPAGATION_REQUIRED</prop>
			 <prop key="update*">PROPAGATION_REQUIRED</prop>
			 <prop key="upadate*">PROPAGATION_REQUIRED</prop>
			 <prop key="delete*">PROPAGATION_REQUIRED</prop>
			 <prop key="import*">PROPAGATION_REQUIRED</prop>
			 <prop key="remove*">PROPAGATION_REQUIRED</prop>
			 <prop key="cancel*">PROPAGATION_REQUIRED</prop>
			 <prop key="create*">PROPAGATION_REQUIRED</prop>
			 <prop key="download*">PROPAGATION_REQUIRED</prop>
			 <prop key="upload*">PROPAGATION_REQUIRED</prop>
			 <prop key="doProcessor*">PROPAGATION_REQUIRED</prop>
			 <prop key="approve*">PROPAGATION_REQUIRED</prop>
			 <prop key="doVerfy*">PROPAGATION_REQUIRED,readOnly</prop>
			 <prop key="list*">PROPAGATION_REQUIRED,readOnly</prop>
			 <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
			 <prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>
			 <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
			 <prop key="search*">PROPAGATION_REQUIRED,readOnly</prop>
			 <prop key="is*">PROPAGATION_REQUIRED,readOnly</prop>
			 <prop key="has*">PROPAGATION_REQUIRED,readOnly</prop>
        </props>
     </property>
   </bean>

	<!-- DBCP数据源 -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="${driverClassName}" />
        <property name="url" value="${url}" />
        <property name="username" value="${username}" />
        <property name="password" value="${password}" />
		<!-- 初始化个数 可修改数量 -->
		<property name="initialSize" value="${initialSize}" />
		<!-- 最大连接数据库连接数,设置为0时,表示没有限制 可修改数量 -->
		<property name="maxActive" value="${maxActive}" />
		<!-- 最大等待秒数,单位为毫秒, 超过时间会报出错误信息 -->
		<property name="maxWait" value="1" />
		<!-- 最大等待连接中的数量,设置为0时,表示没有限制 -->
		<property name="maxIdle" value="1" />
		<!-- 是否自我中断,默认是 false  -->
		<property name="removeAbandoned" value="true" />
		<!-- 几秒后数据连接会自动断开,在removeAbandoned为true,提供该值 -->
		<property name="removeAbandonedTimeout" value="150" />
		<!-- 是否记录中断事件, 默认为 false -->
		<property name="logAbandoned" value="true" />
  	</bean>
  	
  	<!-- DBCP数据源 -->
	<bean id="dataSourceTwo" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="${dbTwo.driverClassName}" />
        <property name="url" value="${dbTwo.url}" />
        <property name="username" value="${dbTwo.username}" />
        <property name="password" value="${dbTwo.password}" />
		<!-- 初始化个数 可修改数量 -->
		<property name="initialSize" value="${dbTwo.initialSize}" />
		<!-- 最大连接数据库连接数,设置为0时,表示没有限制 可修改数量 -->
		<property name="maxActive" value="${dbTwo.maxActive}" />
		<!-- 最大等待秒数,单位为毫秒, 超过时间会报出错误信息 -->
		<property name="maxWait" value="1" />
		<!-- 最大等待连接中的数量,设置为0时,表示没有限制 -->
		<property name="maxIdle" value="1" />
		<!-- 是否自我中断,默认是 false  -->
		<property name="removeAbandoned" value="true" />
		<!-- 几秒后数据连接会自动断开,在removeAbandoned为true,提供该值 -->
		<property name="removeAbandonedTimeout" value="150" />
		<!-- 是否记录中断事件, 默认为 false -->
		<property name="logAbandoned" value="true" />
  	</bean>
  	
	
	<bean id="dynamicDataSource" class="com.siit.digital.framework.common.datasourceswitch.impl.DynamicDataSource" >
	    <!-- 通过key-value的形式来关联数据源 -->
		<property name="targetDataSources">
			<map>
				<entry value-ref="dataSource" key="dataSource"></entry>
				<entry value-ref="dataSourceTwo" key="dataSourceTwo"></entry>
			</map>
		</property>
        <!-- 默认数据源 -->
		<property name="defaultTargetDataSource" ref="dataSource" >
		</property>
	</bean>
  	
  	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
       <property name="dataSource">
           <ref local="dynamicDataSource" />
       </property>
       <property name="mappingLocations">
       		<list>
	       		<value>classpath*:modelConfig/db1/${dataSource}/*.hbm.xml</value>
	       		<value>classpath*:modelConfig/db2/${dbTwo.dataSource}/*.hbm.xml</value>
       		</list>		
	   </property>
     <property name="hibernateProperties">
	    <props>
	       <prop key="hibernate.dialect">${hibernate.dialect}</prop>
	       <prop key="hibernate.show_sql">true</prop>
	    </props>
	</property>
  </bean>
  
  <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
       <property name="sessionFactory">
           <ref local="sessionFactory" />
       </property>
  </bean>
  
</beans>

properties配置

driverClassName=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@192.168.2.112:1521:ORCL
username=imssc5
password=sa
initialSize=5
maxActive=50
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
dataSource=oracle
jndiName=image

dbTwo.driverClassName=com.mysql.cj.jdbc.Driver
dbTwo.url=jdbc\:mysql\://localhost\:3306/zgh?serverTimezone=GMT&autoReconnect=true&characterEncoding=utf-8&useSSL=false
dbTwo.username=root
dbTwo.password=gao24
dbTwo.initialSize=5
dbTwo.maxActive=50
dbTwo.dataSource=mysql
dbTwo.hibernate.dialect=org.hibernate.dialect.MySQLDialect
DynamicDataSource类
public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        // 获取数据源标识
        return DynamicDataSourceHolder.getDataSource();
    }

}
DynamicDataSourceHolder类
public class DynamicDataSourceHolder {
    // 线程本地环境  
    private static final ThreadLocal contextHolder = new ThreadLocal();  
      
    // 设置数据源类型  
    public static void setDataSourceType(String dataSourceType) {  
        contextHolder.set(dataSourceType);  
    }  
  
    // 获取数据源类型  
    public static String getDataSourceType() {  
        return (String) contextHolder.get();  
    }  
  
    // 清除数据源类型  
    public static void clearDataSourceType() {  
        contextHolder.remove();  
    }  

}

切换可以直接根据注册进动态数据源的key值进行选择。
需要注意的是,切换数据源要在事务之前就可以了。否则不生效。

@Controller
public class Test {
    @Autowired
    private DynDataSourceService dataSourceService;
    @RequestMapping("/Test")
    public String test() {
        DynamicDataSourceHolder.setDataSource("dataSourceTwo");
        return dataSourceService.find();
    }
}

参考:

https://blog.csdn.net/qq_35830949/article/details/80885745

https://www.cnblogs.com/kongpeng/p/6483568.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值