欢迎光临
一个有态度、有温度的分享型博客

SpringMVC框架整合Mybatis配置多个数据库

环境

  • Spring:3.1;
  • Mybatis:3.1;
  • 数据库:我这里是不存在主从关系的、相互独立的两个oracle数据库;

需求

系统本身是Oracle数据库,但是系统中的个别功能是查询另外的数据库(我这里是echarts指标展示图部分),因此需要对mybatis进行配置,需要同时连接两个数据库,这两个数据库之间不存在任何关系。

实现

简单的在配置文件里再添加一个datasource的bean、sqlSessionFactory、mapperScannerConfigurer和transactionManager,把数据库连接信息改一下的方式是行不通的,这里是使用Spring提供的AbstractRoutingDataSource类来根据请求路由到不同的数据源。

1.Mybatis配置文件

    <!-- 引入jdbc配置文件 -->
    <context:property-placeholder location="classpath:jdbc.properties" />

    <!--动态数据源dataSource-->
    <bean id="dynamicDataSource" class="com.cdsoft.platform.common.DynamicDataSource" >
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <!--通过不同的key决定用哪个dataSource-->
                <entry value-ref="dataSource" key="dataSource"></entry>
                <entry value-ref="dataSourceEcharts" key="dataSourceEcharts"></entry>
            </map>
        </property>
        <!--设置默认的dataSource-->
        <property name="defaultTargetDataSource" ref="dataSource">
        </property>
    </bean>

    <!--创建jdbc数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${driverClassName}" />
        <property name="url" value="${url}" />
        <property name="username" value="${username}" />
        <property name="password" value="${password}" />
    </bean>

    <!--echarts指标展示数据源配置-->
    <bean id="dataSourceEcharts" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close">
        <property name="driverClassName" value="${driverClassName}" />
        <property name="url" value="${echarts.url}" />
        <property name="username" value="${echarts.username}" />
        <property name="password" value="${echarts.password}" />
    </bean>

    <!-- 创建SqlSessionFactory,同时指定数据源 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dynamicDataSource" />
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
    </bean>

    <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dynamicDataSource" />
    </bean>

    <!-- 可通过注解控制事务 -->
    <tx:annotation-driven/>

    <!-- Mapper接口所在包名,Spring会自动查找其下的Mapper -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.cdsoft.*.mapper,com.cdsoft.mcm.*.mapper" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

2.利用ThreadLocal解决线程安全问题,实现各个数据源之间的切换

package com.cdsoft.platform.common;

import org.apache.commons.lang.StringUtils;

public class CustomerContextHolder {
    public static final String DATA_SOURCE_BASIC = "dataSource";
    public static final String DATA_SOURCE_ECHARTS = "dataSourceEcharts";

    //用ThreadLocal来设置当前线程使用哪个dataSource
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

    public static void setCustomerType(String customerType) {
        contextHolder.set(customerType);
    }

    public static String getCustomerType() {
        String dataSource = contextHolder.get();
        if (StringUtils.isEmpty(dataSource)) {
            return DATA_SOURCE_BASIC;
        } else {
            return dataSource;
        }
    }

    public static void clearCustomerType() {
        contextHolder.remove();
    }
}

3.继承Spring的AbstractRoutingDataSource类,并实现determineCurrentLookupKey方法

package com.cdsoft.platform.common;

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

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return CustomerContextHolder.getCustomerType();
    }
}

4.在service层或dao层进行使用

package com.cdsoft.mcm.index.service.impl;

import com.cdsoft.mcm.index.mapper.QueryIndexMapper;
import com.cdsoft.mcm.index.service.IQueryIndexService;
import com.cdsoft.platform.common.CustomerContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;

@Service
public class QueryIndexServiceImpl implements IQueryIndexService {
    @Resource
    private QueryIndexMapper queryIndexMapper;

    @Override
    public List<HashMap> queryChSzIndex(HashMap params) {
        System.out.println(CustomerContextHolder.getCustomerType()+"===============datasource");
        CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_ECHARTS);
        System.out.println(CustomerContextHolder.getCustomerType()+"===============datasource");
        return queryIndexMapper.queryChSzIndex(params);
    }
}

到此,就实现了两个数据库之间的正常切换。

参考文章:

  1. 【Java】一次SpringMVC+ Mybatis 配置多数据源经历
  2. 利用Spring的AbstractRoutingDataSource解决多数据源的问题

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址