项目中我们经常会遇到多数据源的问题,尤其是数据同步或定时任务等项目更是如此。多数据源让人最头痛的,不是配置多个数据源,而是如何能灵活动态的切换数据源。例如在一个spring和hibernate的框架的项目中,我们在spring配置中往往是配置一个dataSource来连接数据库,然后绑定给sessionFactory,在dao层代码中再指定sessionFactory来进行数据库操作。  正如上图所示,每一块都是指定绑死的,如果是多个数据源,也只能是下图中那种方式。  可看出在Dao层代码中写死了两个SessionFactory,这样日后如果再多一个数据源,还要改代码添加一个SessionFactory,显然这并不符合开闭原则。 那么正确的做法应该是  代码如下: 1. applicationContext.xml 2. DynamicDataSource.class - package com.core;
-
- import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
-
- public class DynamicDataSource extends AbstractRoutingDataSource{
-
- @Override
- protected Object determineCurrentLookupKey() {
- return DatabaseContextHolder.getCustomerType();
- }
-
- }
复制代码 3. DatabaseContextHolder.class - package com.core;
-
- public class DatabaseContextHolder {
-
- private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
-
- public static void setCustomerType(String customerType) {
- contextHolder.set(customerType);
- }
-
- public static String getCustomerType() {
- return contextHolder.get();
- }
-
- public static void clearCustomerType() {
- contextHolder.remove();
- }
- }
复制代码 4. DataSourceInterceptor.class - package com.core;
-
- import org.aspectj.lang.JoinPoint;
- import org.springframework.stereotype.Component;
-
- @Component
- public class DataSourceInterceptor {
-
- public void setdataSourceOne(JoinPoint jp) {
- DatabaseContextHolder.setCustomerType("dataSourceOne");
- }
-
- public void setdataSourceTwo(JoinPoint jp) {
- DatabaseContextHolder.setCustomerType("dataSourceTwo");
- }
- }
复制代码 5. po实体类 - package com.po;
-
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.Id;
- import javax.persistence.Table;
-
- @Entity
- @Table(name = "BTSF_BRAND", schema = "hotel")
- public class Brand {
-
- private String id;
- private String names;
- private String url;
-
- @Id
- @Column(name = "ID", unique = true, nullable = false, length = 10)
- public String getId() {
- return this.id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- @Column(name = "NAMES", nullable = false, length = 50)
- public String getNames() {
- return this.names;
- }
-
- public void setNames(String names) {
- this.names = names;
- }
-
- @Column(name = "URL", length = 200)
- public String getUrl() {
- return this.url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
- }
复制代码 - package com.po;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.Id;
- import javax.persistence.Table;
-
- @Entity
- @Table(name = "CITY", schema = "car")
- public class City {
-
- private Integer id;
-
- private String name;
-
- @Id
- @Column(name = "ID", unique = true, nullable = false)
- public Integer getId() {
- return id;
- }
-
- public void setId(Integer id) {
- this.id = id;
- }
-
- @Column(name = "NAMES", nullable = false, length = 50)
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
- }
复制代码 6. BrandDaoImpl.class - package com.dao.one;
-
- import java.util.List;
-
- import javax.annotation.Resource;
-
- import org.hibernate.Query;
- import org.hibernate.SessionFactory;
- import org.springframework.stereotype.Repository;
-
- import com.po.Brand;
-
- @Repository
- public class BrandDaoImpl implements IBrandDao {
-
- @Resource
- protected SessionFactory sessionFactory;
-
- @SuppressWarnings("unchecked")
- @Override
- public List<Brand> findAll() {
- String hql = "from Brand";
- Query query = sessionFactory.getCurrentSession().createQuery(hql);
- return query.list();
- }
- }
复制代码 7. CityDaoImpl.class - package com.dao.two;
-
- import java.util.List;
-
- import javax.annotation.Resource;
-
- import org.hibernate.Query;
- import org.hibernate.SessionFactory;
- import org.springframework.stereotype.Repository;
-
- import com.po.City;
-
- @Repository
- public class CityDaoImpl implements ICityDao {
-
- @Resource
- private SessionFactory sessionFactory;
-
- @SuppressWarnings("unchecked")
- @Override
- public List<City> find() {
- String hql = "from City";
- Query query = sessionFactory.getCurrentSession().createQuery(hql);
- return query.list();
- }
- }
复制代码 8. DaoTest.class - package com.test;
-
- import java.util.List;
-
- import javax.annotation.Resource;
-
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.test.context.ContextConfiguration;
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
- import org.springframework.test.context.transaction.TransactionConfiguration;
-
- import com.dao.one.IBrandDao;
- import com.dao.two.ICityDao;
- import com.po.Brand;
- import com.po.City;
-
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(locations = "classpath:com/resource/applicationContext.xml")
- @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
- public class DaoTest {
-
- @Resource
- private IBrandDao brandDao;
-
- @Resource
- private ICityDao cityDao;
-
- [url=home.php?mod=space&uid=5447]@test[/url]
- public void testList() {
- List<Brand> brands = brandDao.findAll();
- System.out.println(brands.size());
-
- List<City> cities = cityDao.find();
- System.out.println(cities.size());
- }
- }
复制代码 利用aop,达到动态更改数据源的目的。当需要增加数据源的时候,我们只需要在applicationContext配置文件中添加aop配置,新建个DataSourceInterceptor即可。而不需要更改任何代码。 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持程序员之家。 |