JavaWeb中的多数据源开发

从我们接触Javaweb开始,ssh框架或者ssm等或许是惊叹于框架的强大之处还是自身的迷茫,一直没有注意到一个问题就是:在我的项目中在spring中所配置的数据源都是指向单一数据库,都是单数据源,一个指向数据库的url,数据库驱动,用户名密码等的配置。但是随着自己工作时间的延长在新公司我接触到了新的问题。多数据源的配置和使用。

在实际的开发中有很多时候我们是要与其他公司进行合作,有的合作公司会给咱们一系列的数据接口我们只需要做好数据展示等工作,但是有的公司则是会向我们开放一个数据库的端口,让我们可以对数据库进行查询操作。而且这一部分功能是嵌入在我们原来的系统中的,这时候就会发现我们在我们的项目中用到了两个数据源,在这之前我们好像对于多数据源的开发毫无经验。

经过公司大神的指导以及自己的百度查询结果。get到了这个多数据源开发的技能,首先在spring的配置文件中配置自己的与数据库进行连接的bean,需要几个,有几个配几个,然后就是需要写一个类,这个类就是实现多数据源切换的关键了。这个类需要继承spring提供的一个抽象类:org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource,然后需要实现其中的一个方法:determineCurrentLookupKey这个方法的作用就是返回要使用的数据源的名称,注意这个操作是要与将来数据库中的其他配置联动的:

<bean id="multipleDataSource" class="com.base.multidb.MyDataSource">
        <property name="defaultTargetDataSource" ref="主数据源"/>
        <property name="targetDataSources">
            <map>
                <entry key=" 主数据源" value-ref="主数据源"/>
   <entry key=" 数据源1" value-ref="数据源1"/>

<entry key=" 数据源2" value-ref="数据源2"/>
            </map>
        </property>
    </bean>

在上面的配置中所用到的三个数据源(与数据库的连接bean)是自己所配置的存在的,在上面所配置的bean中defaulttargetDataSource代表的是主数据源即默认的数据源,下面的targetDataSources中所属的map中所配置的就是所有的数据源,有几个用到几个就配置几个,此时就理解了上面自己所写的实现spring提供的抽象类的方法的操作含义了,那个方法的主要目的就是返回一个所要使用的数据源的名称,而这个数据源的名称会去与所配置的map中所有数据源的key进行匹配,一致的数据源就会是这个线程操作所使用到的数据源,通过上面的操作基本上就可以实现多数据源的切换了,自己所实现的那个类其实就是一个数据源的代理对象,然后将这个对象传递给sqlsessionfactory即可进行数据库的相关操作获取sqlsession操作数据库了,

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="multipleDataSource"/>
<property name="mapperLocations">
<list>
  <value>classpath:com/mapper/*Mapper.xml</value>
  <value>classpath:com2/mapper/*/*Mapper.xml</value>
</list>
</property>
    </bean>

 而在事物配置上也是,将代理数据源配置到事物中的DataSource即可


  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 

  <property name="dataSource" ref="multipleDataSource" /> 
  </bean>

配置说完了,下面该代理数据源的实现了:


package com.base.multidb;


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


public class MyChangeDateSource extends AbstractRoutingDataSource{


private static final ThreadLocal<String> datasourceKey = new ThreadLocal<String>();

public static void setDataSource(String useSource){
datasourceKey.set(useSource);
}

@Override
protected Object determineCurrentLookupKey() {
// TODO Auto-generated method stub
return datasourceKey.get();
}


}

这个操作没有多少可说的,因为我也不是特别懂偷笑,不过还是需要说两句ThreadLocal是在多线程环境中使用的,创建一个对象只属于当前线程并在当前线程中共享,set方法就是我们在开发中进行业务逻辑操作之前需要进行数据源切换的一个操作方法。而最后一个方法就是继承spring提供的抽象类后要求必须实现的一个方法,这个方法中需要进行一个操作,就是返回你所需要使用的数据源的key(在配置文件中有配置)


在接下来说说具体的数据源切换的使用:

首先,这个数据源的切换操作所进行的位置个人认为是需要在action或者controller中进行的,因为service中一般都是一些业务逻辑操作一般是需要事物的(比如多数据操作,某一个出错的数据统一回滚)所以需要在Action中进行切换,如果写的不对望各位大神留言批判。

具体操作没什么:在action中进行数据库相关操作前加入一行代码:

MyChangeDateSource.setDataSource(""); 将所要切换的数据源的对应的key作为参数传递进去即可

这样这个key就保存在ThreadLocal的对象中,对于这个线程来说所使用的的数据源就一直都是正确所需要的数据源(因为这个controller方法作为后天的一个部分是在一个多线程环境中可能会有很多个线程都会进行访问,这样就将数据源匹配给对应的线程操作不会出现混乱)

最后要提一句:这里指的多数据源是广义上的数据源,即一个数据源就是指一个数据库服务器中的所有数据库,多数据源是指夸服务器的多个数据库的操作,如果仅仅是一个数据库服务器上的多个数据库的操作的话没有必要进行多数据源的配置。在进行同源(同一个数据库服务器)数据库进行操作的时候只需要在sql语句里面稍加变动即可,即在写表的时候不能直接写表名,而是需要:数据库  【.】 该库下的表名 然后进行其他的数据库操作

原文地址:https://www.cnblogs.com/520future/p/8549112.html