`
xgbjmxn
  • 浏览: 270549 次
  • 性别: Icon_minigender_1
  • 来自: 新乡
社区版块
存档分类
最新评论

Spring 动态设置数据源

阅读更多
Spring 动态设置数据源
Spring数据结构HibernateDB2DAO.Spring2.0.1以后的版本已经支持配置多数据源,并且可以在运行的时候动态加载不同的数据源。通过继承AbstractRoutingDataSource就可以实现多数据源的动态转换。目前做的项目就是需要访问12个数据源,每个数据源的表结构都是相同的,所以要求数据源的变动对于编码人员来说是透明,也就是说同样SQL语句在不同的环境下操作的数据库是不一样的。具体的配置如下:
一、首先需要写一个静态的键值对照类:


代码

Java代码 
1.package cn.com.xinli.ccp.dynamicds;      
2.     
3.public class DataSourceMap {      
4.    public static final String Admin="Admin";      
5.    public static final String Yxh = "Yxh";      
6.}  
package cn.com.xinli.ccp.dynamicds;   
  
public class DataSourceMap {   
    public static final String Admin="Admin";   
    public static final String Yxh = "Yxh";   
}



这个类主要在使用的时候当作获得数据源的标志使用。
二、建立一个获得和设置上下文的类:


代码

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


这个主要负责设置上下文环境和获得上下文环境。
三、建立动态数据源类,这个类必须继承AbstractRoutingDataSource:

代码

Java代码 
1.package cn.com.xinli.ccp.dynamicds;      
2.     
3.import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;      
4.     
5.public class DynamicDataSource extends AbstractRoutingDataSource {      
6.     
7.    protected Object determineCurrentLookupKey() {      
8.        // TODO Auto-generated method stub      
9.        return CustomerContextHolder.getCustomerType();      
10.    }      
11.     
12.}  
package cn.com.xinli.ccp.dynamicds;   
  
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;   
  
public class DynamicDataSource extends AbstractRoutingDataSource {   
  
    protected Object determineCurrentLookupKey() {   
        // TODO Auto-generated method stub   
        return CustomerContextHolder.getCustomerType();   
    }   
  
}

这个类实现了determineCurrentLookupKey方法,该方法返回一个Object,一般是返回字符串,也可以是枚举类型。该方法中直接使用了CustomerContextHolder.getCustomerType()方法获得上下文环境并直接返回。
四、编写spring的配置文件配置数据源

代码

Java代码 
1.<bean id="parentDataSource"     
2.            class="org.springframework.jdbc.datasource.DriverManagerDataSource">     
3.            <property name="driverClassName">     
4.                <value>COM.ibm.db2.jdbc.net.DB2Driver</value>     
5.            </property>     
6.            <property name="url">     
7.                <value>jdbc:db2:127.0.0.1:TEST</value>     
8.            </property>     
9.    </bean>     
10.          
11.    <bean id="adminDataSource" parent="parentDataSource">     
12.        <property name="username" value="admin"/>     
13.        <property name="password" value="master997mb"/>     
14.    </bean>     
15.          
16.    <bean id="yxhDataSource" parent="parentDataSource">     
17.        <property name="username" value="yxh"/>     
18.        <property name="password" value="yxh"/>     
19.    </bean>   
<bean id="parentDataSource"  
            class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
            <property name="driverClassName">  
                <value>COM.ibm.db2.jdbc.net.DB2Driver</value>  
            </property>  
            <property name="url">  
                <value>jdbc:db2:127.0.0.1:TEST</value>  
            </property>  
    </bean>  
       
    <bean id="adminDataSource" parent="parentDataSource">  
        <property name="username" value="admin"/>  
        <property name="password" value="master997mb"/>  
    </bean>  
       
    <bean id="yxhDataSource" parent="parentDataSource">  
        <property name="username" value="yxh"/>  
        <property name="password" value="yxh"/>  
    </bean> 

在这个配置中可以看到首先有个parentDataSource,这个主要配置一些数据源的公用信息,项目中都是链接DB2数据库;adminDataSource和yxhDataSource是根据不同需要配置的个性化信息,但都必须加parent属性,值为parentDataSource。这样就配置好了2个数据源信息。当然如果链接的多数据源是不同类型的两个数据库,那么parentDataSource就可以不要了,直接配置两个不同的数据源链接就可以了。
五、编写spring配置文件配置多数据源映射关系

代码

Java代码 
1.<bean id="dataSource" class="cn.com.xinli.ccp.dynamicds.DynamicDataSource">     
2.       <property name="targetDataSources">     
3.          <map key-type="java.lang.String">     
4.             <entry key="Yxh" value-ref="yxhDataSource"/>     
5.          </map>     
6.       </property>     
7.       <property name="defaultTargetDataSource" ref="adminDataSource"/>     
8.    </bean>   
<bean id="dataSource" class="cn.com.xinli.ccp.dynamicds.DynamicDataSource">  
       <property name="targetDataSources">  
          <map key-type="java.lang.String">  
             <entry key="Yxh" value-ref="yxhDataSource"/>  
          </map>  
       </property>  
       <property name="defaultTargetDataSource" ref="adminDataSource"/>  
    </bean> 

在这个配置中第一个property属性配置目标数据源,<map key-type="java.lang.String">中的key-type必须要和静态键值对照类DataSourceMap中的值的类型相同;<entry key="Yxh" value-ref="yxhDataSource"/>中key的值必须要和静态键值对照类中的值相同,如果有多个值,可以配置多个<entry>标签。第二个property属性配置默认的数据源。
六、配置hibernate。
Hibernate的配置和普通的hibernate、spring结合的配置一样

代码

Java代码 
1.<bean id="sessionFactory"     
2.        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">     
3.        <!-- to override, use the "SpringDatasourceConfig" snippet in your project -->     
4.        <property name="dataSource">     
5.            <ref local="dataSource" />     
6.        </property>     
7.        <property name="mappingResources">     
8.            <list>     
9.                <value>     
10.                    cn/com/xinli/ccp/entity/User.hbm.xml      
11.                </value>     
12.                <value>     
13.                    cn/com/xinli/ccp/entity/Test.hbm.xml      
14.                </value>     
15.            </list>     
16.        </property>     
17.        <property name="hibernateProperties">     
18.            <props>     
19.                <prop key="hibernate.dialect">     
20.                    org.hibernate.dialect.DB2Dialect      
21.                </prop>     
22.                      
23.                <prop key="hibernate.show_sql">true</prop>     
24.                <prop key="hibernate.use_outer_join">true</prop>     
25.                <prop key="hibernate.jdbc.batch_size">50</prop>     
26.                <prop key="hibernate.jdbc.fetch_size">5</prop>     
27.                <prop key="hibernate.connection.pool_size">2</prop>     
28.                <prop key="hibernate.connection.autocommit">false</prop>     
29.                <prop key="hibernate.cache.use_query_cache">false</prop>     
30.                <prop key="hibernate.max_fetch_depth">1</prop>     
31.                <prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>     
32.            </props>     
33.        </property>     
34.    </bean>     
35.     
36.<bean id="mydao" class="cn.com.xinli.ccp.dao.HibernateBaseDao">     
37.        <property name="sessionFactory">     
38.            <ref local="sessionFactory" />     
39.        </property>     
40.    </bean>   
<bean id="sessionFactory"  
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
        <!-- to override, use the "SpringDatasourceConfig" snippet in your project -->  
        <property name="dataSource">  
            <ref local="dataSource" />  
        </property>  
        <property name="mappingResources">  
            <list>  
                <value>  
                    cn/com/xinli/ccp/entity/User.hbm.xml   
                </value>  
                <value>  
                    cn/com/xinli/ccp/entity/Test.hbm.xml   
                </value>  
            </list>  
        </property>  
        <property name="hibernateProperties">  
            <props>  
                <prop key="hibernate.dialect">  
                    org.hibernate.dialect.DB2Dialect   
                </prop>  
                   
                <prop key="hibernate.show_sql">true</prop>  
                <prop key="hibernate.use_outer_join">true</prop>  
                <prop key="hibernate.jdbc.batch_size">50</prop>  
                <prop key="hibernate.jdbc.fetch_size">5</prop>  
                <prop key="hibernate.connection.pool_size">2</prop>  
                <prop key="hibernate.connection.autocommit">false</prop>  
                <prop key="hibernate.cache.use_query_cache">false</prop>  
                <prop key="hibernate.max_fetch_depth">1</prop>  
                <prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>  
            </props>  
        </property>  
    </bean>  
  
<bean id="mydao" class="cn.com.xinli.ccp.dao.HibernateBaseDao">  
        <property name="sessionFactory">  
            <ref local="sessionFactory" />  
        </property>  
    </bean> 
关于dao的代码这里就省略了。
七、配置结束,可以使用了。

代码

Java代码 
1.public class DaoTest extends TestCase {      
2.     
3.    public void testSave() throws Exception{      
4.        CustomerContextHolder.setCustomerType(DataSourceMap.Admin);//设置数据源      
5.        //hibernate创建实体      
6.        Test test = new Test();      
7.        test.setTest("22222222");      
8.              
9.        mydao.save(test);//使用dao保存实体      
10.              
11.        CustomerContextHolder.setCustomerType(DataSourceMap.Yxh);//设置为另一个数据源      
12.              
13.        mydao.save(test);//使用dao保存实体到另一个库中      
14.              
15.    }      
16.}   
public class DaoTest extends TestCase {   
  
    public void testSave() throws Exception{   
        CustomerContextHolder.setCustomerType(DataSourceMap.Admin);//设置数据源   
        //hibernate创建实体   
        Test test = new Test();   
        test.setTest("22222222");   
           
        mydao.save(test);//使用dao保存实体   
           
        CustomerContextHolder.setCustomerType(DataSourceMap.Yxh);//设置为另一个数据源   
           
        mydao.save(test);//使用dao保存实体到另一个库中   
           
    }   

在项目中对于编码人员对多数据源的切换可以做成透明的,操作同样的dao,就可以访问不同的数据库
补充:使用filter设置数据源

Java代码 
1.public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException       
2.    {       
3.       HttpServletRequest httpRequest = (HttpServletRequest) request;       
4.       Object dataSourceName=httpRequest.getSession().getAttribute("currentDataSource");       
5.           if(dataSourceName!=null&&!"".equals(dataSourceName))       
6.           {       
7.              String name = dataSourceName.toString();       
8.              //System.out.println("使数据源"+name);  
9.              CustomerContextHolder.setCustomerType(name);  
10.           }       
11.           else       
12.           {    
13.               CustomerContextHolder.setCustomerType("publicDataSource");  
14.              //System.out.println("使用默认数据源");       
15.           }       
16.       chain.doFilter(request, response);  
17.       CustomerContextHolder.clearCustomerType();  
18.    } 
分享到:
评论

相关推荐

    真正意义的spring动态切换数据源源码

    创建一个切面,拦截特定的方法,然后在方法执行前后动态设置数据源。这种方式更加灵活,可以根据业务逻辑或方法参数来决定使用哪个数据源。 5. **使用ThreadLocal进行切换**:在多线程环境中,可以利用`ThreadLocal...

    spring动态选择数据源

    本篇文章将探讨“Spring动态选择数据源”这一主题,它允许我们的应用程序根据业务需求在多个数据源之间灵活切换,这在多租户、读写分离等场景下尤其重要。 首先,理解“数据源”在Spring中的概念。数据源...

    spring 动态切换数据源

    在Spring框架中,动态切换数据源是一项重要的功能,它允许应用程序根据业务需求在多个数据库之间灵活切换。这一特性对于多租户系统、读写分离、分布式数据库等场景尤其有用。以下将详细介绍如何实现Spring的动态数据...

    spring动态数据源+mybatis分库分表

    "spring动态数据源+mybatis分库分表"是一个针对大型数据库场景的解决方案,它利用Spring框架的动态数据源功能和MyBatis的SQL映射能力,实现数据库的透明化分片。以下是这个主题的详细知识点: 1. **Spring动态数据...

    spring 动态多数据源配置代码

    下面将详细介绍Spring动态多数据源配置的相关知识点。 1. **为什么要使用多数据源**: 在实际项目中,可能需要连接到不同的数据库,例如,一个用于存储主业务数据,另一个用于日志记录或数据分析。通过多数据源...

    mybatis+spring实现动态切换数据源

    在`mybatis-spring`的配置中,我们指定使用Spring的`SqlSessionFactoryBean`,并将数据源设置为我们的动态数据源。 ```xml &lt;bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"&gt; &lt;!...

    Spring动态切换多数据源Demo

    "Spring动态切换多数据源Demo"是一个示例项目,它展示了如何在Spring中实现灵活的数据源切换。 首先,我们需要了解Spring中的数据源。在Spring中,数据源(DataSource)是Java中定义的javax.sql.DataSource接口的...

    spring动态切换数据源

    在Java的Spring框架中,动态切换数据源是一项重要的功能,尤其在多租户、微服务或者需要根据业务逻辑切换数据库的场景下。本知识点主要围绕如何在Spring中实现数据源的动态切换进行深入探讨。 首先,我们需要理解...

    动态数据源实现spring

    在Spring框架中,动态数据源实现是一个重要的特性,它允许应用程序根据特定的条件或用户需求在运行时切换数据源。这种灵活性对于多租户系统、数据隔离或者在不同环境(如开发、测试、生产)之间切换数据库配置尤其...

    spring boot多数据源配置

    创建一个继承自`AbstractRoutingDataSource`的类,通过设置当前数据源上下文来实现数据源的切换: ```java @Component public class DynamicDataSource extends AbstractRoutingDataSource { @Override ...

    Spring+SpringMVC+Mybatis动态链接多数据源

    本项目“Spring+SpringMVC+Mybatis动态链接多数据源”旨在实现一个灵活、可扩展的数据源切换机制,以适应复杂的业务场景。 Spring框架作为Java领域中最广泛使用的轻量级框架,它提供了强大的依赖注入和AOP(面向切...

    Springcloud 多数库 多数据源整合,查询动态切换数据库

    本主题聚焦于在Spring Cloud环境中实现多数据库和多数据源的整合,并且能够动态切换查询的数据库。这是一个复杂但至关重要的需求,特别是在大型企业级应用中,可能需要根据业务逻辑或用户权限连接到不同的数据库。 ...

    SpringBoot配置多数据源实现动态切换数据源

    本文将深入探讨如何在SpringBoot项目中配置多数据源,并实现数据源的动态切换,帮助你理解和掌握这一核心技能。 首先,我们理解"多数据源"的概念。在SpringBoot应用中,多数据源意味着系统能够连接并操作多个不同的...

    Spring 动态切换数据源

    【Spring 动态切换数据源】是一种在Spring框架中实现的应用程序能够在运行时根据需求动态选择数据源的技术。这种功能对于多数据库环境或者需要对不同数据源执行操作的系统非常有用,例如数据聚合、报表生成等场景。 ...

    spring boot多数据源(AOP注解动态切换)

    通过以上步骤,我们成功地在Spring Boot中实现了基于AOP注解的多数据源动态切换。这使得在运行时可以根据业务需求选择合适的数据源,提高了代码的灵活性和可维护性。在实际项目中,你可能还需要考虑事务管理、数据源...

    Spring Boot多数据源(支持Spring声明式事务切换和回滚).pdf

    - 通过AspectJ实现数据源的动态切换,可以设置在类级别或方法级别,方法级的设置优先于类级。这使得开发者可以根据业务逻辑自由地决定使用哪个数据源。 - 数据源的注册、修改和删除可以在运行时完成,无需重启服务...

    Spring+SpringMvc+MybatisPlus+Aop(自定义注解)动态切换数据源

    在方法执行前,根据注解的值动态设置AbstractRoutingDataSource的数据源标识,从而完成数据源的切换。 5. 实现MybatisPlus的配置,使其能够识别并适配动态数据源。确保在多数据源环境下,每个数据源的...

    SpringBoot+Atomikos+动态多数据源+事务+2种切换数据源的方式

    - **编程式切换**:在业务代码中,可以使用`AbstractRoutingDataSource`的`determineCurrentLookupKey`方法,根据业务需求动态设置当前数据源。 - **声明式切换**:通过AOP切面或者自定义注解,可以在方法执行前...

    springboot 1.5.9+mybatis动态指定数据源

    1. **配置动态数据源**:我们可以使用`AbstractRoutingDataSource`作为基础,这是一个Spring提供的类,它可以基于某种条件(如:注解、线程变量等)动态决定使用哪个具体的数据源。首先,创建一个自定义的`...

    spring整合多数据源完整实例

    在Spring框架中整合多数据源是一项常见的需求,特别是在大型企业应用或者分布式系统中,往往需要连接不同的数据库以满足不同业务场景。本实例将详细介绍如何在Spring中实现这一功能。 首先,我们要理解“多数据源”...

Global site tag (gtag.js) - Google Analytics