Spring配置多数据源

时间:2024-07-08 23:05:14

如何在应用启动之后灵活切换数据源的关键点:

  将SessionFactory接口中的dataSource配置为AbstractRoutingDataSource的instance,sessionFactory在获取datasource的时候会执行AbstractRoutingDataSource的determineCurrentLookupKey()方法,
所以用户要想定制自己切换数据源方式就要继承AbstractRoutingDataSource,然后实现determineCurrentLookupKey()方法。废话不多说,我们马上看例子:

1.简单映射类:User.java

 1 package com.eg.model;
2
3 import javax.persistence.Column;
4 import javax.persistence.Entity;
5 import javax.persistence.Id;
6 import javax.persistence.Table;
7
8 @Entity
9 @Table(name = "user")
10 public class User implements Cloneable{
11 private String user_id;
12 private String name;
13 private String age;
14
15 public User() {
16 }
17
18 @Id
19 @Column(name = "user_id", unique = true, nullable = false, length = 36)
20 public String getUser_id() {
21 return user_id;
22 }
23
24 public void setUser_id(String user_id) {
25 this.user_id = user_id;
26 }
27
28 @Column(name = "name", length = 20)
29 public String getName() {
30 return name;
31 }
32
33 public void setName(String name) {
34 this.name = name;
35 }
36
37 @Column(name = "age", length = 20)
38 public String getAge() {
39 return age;
40 }
41
42 public void setAge(String age) {
43 this.age = age;
44 }
45
46 }

2.DAO层: UserDao.java

 1 package com.eg.dao;
2
3 import org.springframework.stereotype.Repository;
4
5 import com.eg.model.User;
6
7 @Repository
8 public class UsertDao extends BaseHibernateDao<User> {
9
10 }

3.Dao层基类: BaseHibernateDao.java

 1 package com.eg.dao;
2
3
4 import org.apache.commons.logging.Log;
5 import org.apache.commons.logging.LogFactory;
6 import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
7
8 import java.util.List;
9
10 public class BaseHibernateDao<T> extends HibernateDaoSupport
11 {
12 /**
13 * 操作的领域对象的类型
14 */
15 protected Class<T> entityClass;
16
17 protected Log log = (Log) LogFactory.getLog(this.getClass());
18
19
20 /**
21 * 执行HQL查询
22 */
23 public List find(String hql)
24 {
25 return this.getHibernateTemplate().find(hql);
26 }
27
28 }

4.Service层: UserService.java

 1 package com.eg.service;
2
3 import java.util.List;
4
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.stereotype.Service;
7
8 import com.eg.dao.UsertDao;
9 import com.eg.model.User;
10
11 @Service("userService")
12 public class UserService {
13 private UsertDao userDao;
14 @Autowired
15 public UserService(UsertDao dao) {
16 this.userDao = dao;
17 }
18
19 public List<User> findAll() {
20 return userDao.find("from Test");
21 }
22 }

5.两个数据库的配置文件:jdbc.properties

#-----------------------------postgresql datasource1---------------------------------------------#
platform.driverClassName=org.postgresql.Driver
platform.url=jdbc:postgresql://localhost:5432/platform
platform.username=postgres
platform.password=root
platform.timeBetweenEvictionRunsMillis=3600000
platform.minEvictableIdleTimeMillis=21600000 #-----------------------------mysql datasource2--------------------------------------------------#
business.driverClassName=com.mysql.jdbc.Driver
business.url=jdbc:mysql://localhost:3306/platform
business.username=root
business.password= root
business.timeBetweenEvictionRunsMillis=3600000
business.minEvictableIdleTimeMillis=21600000 hiber.dialect=org.hibernate.dialect.MySQL5Dialect

6.容器bean注册文件: bean.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
5 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
6
7
8 <context:component-scan base-package="com.eg.*"></context:component-scan>
9
10 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
11 <property name="locations">
12 <list>
13 <value>classpath:jdbc.properties</value>
14 </list>
15 </property>
16 </bean>
17
18 <bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
19 <property name="url" value="${platform.url}"/>
20 <property name="driverClassName" value="${platform.driverClassName}"/>
21 <property name="username" value="${platform.username}"/>
22 <property name="password" value="${platform.password}"/>
23 <property name="timeBetweenEvictionRunsMillis" value="${platform.timeBetweenEvictionRunsMillis}"></property>
24 <property name="minEvictableIdleTimeMillis" value="${platform.minEvictableIdleTimeMillis}"></property>
25
26 </bean>
27 <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
28 <property name="url" value="${business.url}"/>
29 <property name="driverClassName" value="${business.driverClassName}"/>
30 <property name="username" value="${business.username}"/>
31 <property name="password" value="${business.password}"/>
32 <property name="timeBetweenEvictionRunsMillis" value="${business.timeBetweenEvictionRunsMillis}"></property>
33 <property name="minEvictableIdleTimeMillis" value="${business.minEvictableIdleTimeMillis}"></property>
34 </bean>
35
36 <bean id="dataSource" class="com.eg.dbsource.DynamicDataSource">
37 <!-- 默认数据库 -->
38 <property name="defaultTargetDataSource" ref="dataSource1"/>
39 <property name="targetDataSources" >
40 <!-- 将多个数据源配在这里,我们将通过改变key值来控制切换 -->
41 <map key-type="java.lang.String">
42 <entry key="db1" value-ref="dataSource1"/>
43 <entry key="db2" value-ref="dataSource2"/>
44 </map>
45 </property>
46 </bean>
47
48 <!-- Hibernate Session工厂 -->
49 <bean id="sessionFactory"
50 class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
51 <property name="dataSource" ref="dataSource"/>
52 <property name="packagesToScan">
53 <list>
54 <value>com.eg.model</value>s
55 </list>
56 </property>
57 <property name="hibernateProperties">
58 <props>
59 <prop key="hibernate.dialect">
60 ${hiber.dialect}
61 <!--org.hibernate.dialect.Oracle10gDialect-->
62 </prop>
63 <prop key="hibernate.show_sql">true</prop>
64 <prop key="hibernate.jdbc.batch_size">50</prop>
65 <prop key="hibernate.cache.use_query_cache">false</prop>
66 </props>
67 </property>
68 </bean>
69
70 <!-- Hibernate 模板 -->
71 <bean id="hibernateTemplate"
72 class="org.springframework.orm.hibernate3.HibernateTemplate">
73 <property name="sessionFactory" ref="sessionFactory"/>
74 </bean>
75
76 </beans>

7.继承AbstractRoutingDataSource,并实现其determineCurrentLookupKey方法:DynamicDataSource.java

 1 package com.eg.dbsource;
2
3
4 import java.sql.SQLFeatureNotSupportedException;
5 import java.util.logging.Logger;
6
7 import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
8
9 public class DynamicDataSource extends AbstractRoutingDataSource
10 {
11 protected Object determineCurrentLookupKey() {
12 String type = CustomerContextHolder.getCustomerType();
13 return type;
14 }
15
16 public Logger getParentLogger() throws SQLFeatureNotSupportedException {
17 return null;
18 }
19
20 }

8. 数据源控制器:CustomerContextHolder.java

 1 package com.eg.dbsource;
2
3 public class CustomerContextHolder
4 {
5 private static final ThreadLocal contextHolder = new ThreadLocal();
6
7 public static void setCustomerType(String customerType)
8 {
9 contextHolder.set(customerType);
10 }
11
12 public static String getCustomerType()
13 {
14 return (String) contextHolder.get();
15 }
16
17 public static void clearCustomerType()
18 {
19 contextHolder.remove();
20 }
21 }

9.来测试一下吧:ContextSimulation.java

 1 package com.eg.spring.simulation;
2
3 import java.util.List;
4
5 import org.springframework.context.ApplicationContext;
6 import org.springframework.context.support.ClassPathXmlApplicationContext;
7
8 import com.eg.dbsource.CustomerContextHolder;
9 import com.eg.model.User;
10 import com.eg.service.UserService;
11
12 public class ContextSimulation {
13 public static void main(String[] args) {
14 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
15 UserService testService = (UserService)context.getBean("testService");
16
17 CustomerContextHolder.setCustomerType("db1");
18 List<User> l = testService.findAll();
19
20 CustomerContextHolder.setCustomerType("db2");
21 l = testService.findAll();
22 System.out.println(l.size() +" "+ l.get(0).getName() + " " + l.get(0).getAge());
23 }
24 }