Hibernate的多数据源多数据库

基于SPRING+HIBERNATE的数据库的实现多租户的数据库选择和数据源路由

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:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"

	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd">

	<!-- 加载jdbc.property,hibenrate.properties -->
	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:jdbc.properties</value>
				<value>classpath:hibernate.properties</value>
			</list>
		</property>
		<!-- 容许多次加载属性文件 -->
		<property name="ignoreUnresolvablePlaceholders" value="true" />
	</bean>

	<!-- 连接池 -->
	<bean id="dataSource1" name="dataSource1"
		class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
		<property name="user" value="${jdbc.user}"></property>
		<property name="password" value="${jdbc.password}"></property>
		<property name="initialPoolSize" value="5"></property>
		<property name="minPoolSize" value="1"></property>
		<property name="maxPoolSize" value="100"></property>
		<property name="checkoutTimeout" value="5000"></property>
		<property name="maxIdleTime" value="1800"></property>
		<property name="idleConnectionTestPeriod" value="60"></property>
		<property name="acquireIncrement" value="5"></property>
		<!-- mysql连接超时,默认8小时,解决方案1 -->
		<property name="preferredTestQuery" value="SELECT 1"></property>
		<property name="testConnectionOnCheckin" value="true"></property>
		<property name="testConnectionOnCheckout" value="true"></property>
				 
	</bean>
	<bean id="dataSource2" name="dataSource2"
		class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="jdbcUrl" value="${jdbc.jdbcUrl_1}"></property>
		<property name="user" value="${jdbc.user_1}"></property>
		<property name="password" value="${jdbc.password_1}"></property>
		<property name="initialPoolSize" value="5"></property>
		<property name="minPoolSize" value="1"></property>
		<property name="maxPoolSize" value="100"></property>
		<property name="checkoutTimeout" value="5000"></property>
		<property name="maxIdleTime" value="1800"></property>
		<property name="idleConnectionTestPeriod" value="60"></property>
		<property name="acquireIncrement" value="5"></property>
		<!-- mysql连接超时,默认8小时,解决方案1 -->
		<property name="preferredTestQuery" value="SELECT 1"></property>
		<property name="testConnectionOnCheckin" value="true"></property>
		<property name="testConnectionOnCheckout" value="true"></property>
				
	</bean>
		
	<bean id="dynamicDataSource" class="com.zhenjw.db.DynamicDataSource"  >
		<property name="targetDataSources">
		 <!--标识符类型-->
		 <map key-type="java.lang.String"> 
		 	<entry key="kdataSource1" value-ref="dataSource1"/>
		 	<entry key="kdataSource2" value-ref="dataSource2"/>
		 </map>
		 
		 </property>
		 
		 <property name="defaultTargetDataSource" ref="dataSource1" />
		 
	</bean>
		
	<!-- hibernate4的sessionFacotry,hibernate4没有模版对象,直接使用sessionFactory,hibenrate4默认支持注解 -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		
		<property name="dataSource" ref="dynamicDataSource"></property>
		
		<!-- hibernate注解搜索路径 * 指定有注解的Hibenrate实体类的包 -->
		<property name="packagesToScan">
			<list>
				<value>com.zhenjw.oa.**.entity</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<!-- 设置方言、显示等 -->
				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
				<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
				<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
				<prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>
				<prop key="hibernate.autoReconnect">${hibernate.autoreconnect}</prop>
				<!-- 设置数据库批量查询最大数量 -->
				<prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop>
				<!-- 设置数据库批量更新、添加、删除最大数量 -->
				<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
				
				<!-- 二级缓存配置 -->
				<!-- 是否开启二级缓存 -->
				<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
				<!-- 是否开启查询时的二级缓存,由于命中率很低,通常关闭 -->
				<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
				<!-- 设置二级缓存实现类 -->
				<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
				
				<!-- 如果是oracle 11g,需要制定默认schema <prop key="hibernate.default_schema">${hibernate.default_schema}</prop> -->
			</props>
		</property>
	</bean>
	<!-- 多数据源 -->
	 

	<!-- hibernate4的sessionFacotry,hibernate4没有模版对象,直接使用sessionFactory,hibenrate4默认支持注解 -->
	  
	<!-- 注解搜索路径 -->
	<context:component-scan base-package="com.zhenjw" />
		
	<!-- 支持注解依赖注入 -->
	<context:annotation-config />	
	 
</beans>

java源代码

package com.zhenjw.db;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource{

	private Map dataSourceMap=new HashMap();
	
	@Override
	protected Object determineCurrentLookupKey() {
		// TODO Auto-generated method stub
		//数据源的选择,根据自己的业务修改具体的实现,是返回数据源的key
		String sp = SpObserver.getSp();
		
		return sp;
	}

	@Override
	public Connection getConnection() throws SQLException {
		// TODO Auto-generated method stub
		Connection a= super.getConnection();
		//用于选择数据库的逻辑,基于自己的业务规则进行修改
		a.prepareStatement("use oa_2 ").executeUpdate();
		return a;
	}
	
	
}
package com.zhenjw.db;

public class SpObserver {

	 private static ThreadLocal local = new ThreadLocal();
	 
	 private static String sp;
	 
	 public static void putSp(String sp) {

		 local.set(sp);

	 } 

	 public static String getSp() { 

		 return (String)local.get();    

	 } 
	 
}
package test.db;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.zhenjw.db.BaseDaoImpl;
import com.zhenjw.db.SpObserver;
import com.zhenjw.oa.wzaccount.entity.WzAccount;

public class TestDataSource {

	//private static ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext-base.xml");
	
	private static ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext-base2.xml");
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		SpObserver.putSp("kdataSource2");
		
		BaseDaoImpl baseDao=ac.getBean(BaseDaoImpl.class);
		
		System.out.println(baseDao);
		WzAccount account=new WzAccount("zhenjw3");
		baseDao.create(account);
		
		System.out.println("Over");

	}

}

DAO层按hibernate的普通调用方式就可以了。结合具体的项目具体的实现有时间再细化,已经测试过可以向不同的数据源不同的数据库中增加数据。其它的功能应该也没有问题。

相关推荐