Hibernate's multi-data source multi-database

Multi-tenant database selection and data source routing based on SPRING+HIBERNATE database

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">

	<!-- Load 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>
		<!-- Allow multiple loading of property files-->
		<property name="ignoreUnresolvablePlaceholders" value="true" />
	</bean>

	<!-- connection pool -->
	<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 connection timeout, default 8 hours, solution 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 connection timeout, default 8 hours, solution 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">
		 <!--Identifier type-->
		 <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>
		
	<!-- sessionFacotry of hibernate4, hibernate4 has no template object, use sessionFactory directly, hibenrate4 supports annotations by default -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		
		<property name="dataSource" ref="dynamicDataSource"></property>
		
		<!-- hibernate annotation search path* specifies the package of the annotated Hibenrate entity class -->
		<property name="packagesToScan">
			<list>
				<value>com.zhenjw.oa.**.entity</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<!-- Set dialect, display, etc.-->
				<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>
				<!-- Set the maximum number of database batch queries-->
				<prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop>
				<!-- Set the maximum number of database batch updates, additions and deletions-->
				<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
				
				<!-- L2 cache configuration-->
				<!-- Whether to enable the second level cache -->
				<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
				<!-- Whether to open the second-level cache when querying, because the hit rate is very low, it is usually closed -->
				<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
				<!-- Set the second level cache implementation class-->
				<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
				
				<!-- If it is oracle 11g, you need to make a default schema <prop key="hibernate.default_schema">${hibernate.default_schema}</prop> -->
			</props>
		</property>
	</bean>
	<!-- Multiple data sources -->
	 

	<!-- sessionFacotry of hibernate4, hibernate4 has no template object, use sessionFactory directly, hibenrate4 supports annotations by default -->
	  
	<!-- Annotation search path-->
	<context:component-scan base-package="com.zhenjw" />
		
	<!-- Support annotation dependency injection-->
	<context:annotation-config />	
	 
</beans>

 

java source code

 

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
		//The choice of data source, modify the specific implementation according to your own business, is the key to return the data source
		String sp = SpObserver.getSp();
		
		return sp;
	}

	@Override
	public Connection getConnection() throws SQLException {
		// TODO Auto-generated method stub
		Connection a= super.getConnection();
		//The logic used to select the database, modify it based on your own business rules
		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");

	}

}

 

The DAO layer can be called in the normal way of hibernate. Combined with the specific implementation of the specific project, there is time to refine it, and it has been tested that data can be added to different data sources and different databases. Other functions should be fine.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326739990&siteId=291194637