springBoot+mybatis多数据源配置

Posted 波子汽水yeah

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springBoot+mybatis多数据源配置相关的知识,希望对你有一定的参考价值。

方案一 静态按mapper文件目录分

数据源

spring.datasource.coupon.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.coupon.jdbc-url=jdbc:mysql://127.0.0.1:8080/miu_coupon_server?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.coupon.username=coupon_test
spring.datasource.coupon.password=test

spring.datasource.activity.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.activity.jdbc-url=jdbc:mysql://127.0.0.1:8077/miu_act?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.activity.username=act_mycat
spring.datasource.activity.password=test

新建数据源1配置

 package com.test.marketing.activity.config;

import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Slf4j
@Configuration
@MapperScan(basePackages = "com.test.marketing.activity.dao.apply.mybatis.mapper",
        "com.test.marketing.activity.dao.act.mybatis.mapper",
        "com.test.marketing.activity.dao.comment.mybatis.mapper",
        "com.test.marketing.activity.dao.community.author.mybatis.mapper",
        "com.test.marketing.activity.dao.community.clockin.mybatis.mapper",
        "com.test.marketing.activity.dao.community.complaint.mybatis.mapper",
        "com.test.marketing.activity.dao.community.interest.mybatis.mapper",
        "com.test.marketing.activity.dao.community.recommend.mybatis.mapper",
        "com.test.marketing.activity.dao.icsf.mybatis.mapper",
        "com.test.marketing.activity.dao.invite.mybatis.mapper",
        "com.test.marketing.activity.dao.lottery.mybatis.mapper"
, sqlSessionFactoryRef = "sqlSessionFactory1")
public class Datasource1Configuration 
    @Value("$mybatis.mapper-locations")
    private String mapperLocation;
    @Value("$spring.datasource.url")
    private String jdbcUrl;
    @Value("$spring.datasource.driver-class-name")
    private String driverClassName;
    @Value("$spring.datasource.username")
    private String username;
    @Value("$spring.datasource.password")
    private String password;

    @Value("$spring.datasource.coupon.jdbc-url")
    private String couponjdbcUrl;
    @Value("$spring.datasource.coupon.driver-class-name")
    private String coupondriverClassName;
    @Value("$spring.datasource.coupon.username")
    private String couponusername;
    @Value("$spring.datasource.coupon.password")
    private String couponpassword;

    @Bean(name = "dataSource1")
    @Primary
    public DataSource dataSource() 
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(jdbcUrl);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    

    @Primary
    @Bean("sqlSessionFactory1")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource1") DataSource dataSource) throws Exception 
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/activity/**/**Mapper.xml"));
        log.info("获取数据库连接-old-activity=", dataSource.toString());
        return sqlSessionFactoryBean.getObject();
    

    @Primary
    @Bean("sqlSessionTemplate1")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory) 
        return new SqlSessionTemplate(sqlSessionFactory);
    

    @Primary
    @Bean("transactionManager1")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource1") DataSource dataSource) 
        return new DataSourceTransactionManager(dataSource);
    




数据源2配置

 package com.test.marketing.activity.config;

import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Slf4j
@Configuration
@MapperScan(basePackages = "com.test.marketing.activity.dao.coupon.mybatis.mapper", sqlSessionFactoryRef = "sqlSessionFactory2")
public class DatasourceCouponConfiguration 
    @Value("$mybatis.mapper-locations")
    private String mapperLocation;
    @Value("$spring.datasource.coupon.jdbc-url")
    private String jdbcUrl;
    @Value("$spring.datasource.coupon.driver-class-name")
    private String driverClassName;
    @Value("$spring.datasource.coupon.username")
    private String username;
    @Value("$spring.datasource.coupon.password")
    private String password;

    @Bean(name = "dataSource2")
    public DataSource dataSource() 
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(jdbcUrl);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    

    @Bean("sqlSessionFactory2")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource2") DataSource dataSource) throws Exception 
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/coupon/**Mapper.xml"));
        log.info("获取数据库连接-coupon=", dataSource.toString());
        return sqlSessionFactoryBean.getObject();
    

    @Bean("sqlSessionTemplate2")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory) 
        return new SqlSessionTemplate(sqlSessionFactory);
    

    @Bean("transactionManager2")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource2") DataSource dataSource2) 
        return new DataSourceTransactionManager(dataSource2);
    


注意扫描路径和mapper文件要对应 默认数据源添加 @Primary 注解不然会报错

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available: expected single matching bean but found 2: transactionManager1,transactionManager2

参考此篇

方案二 动态数据源
新建配置类


import com.test.marketing.activity.api.coupon.common.DBSource;
import com.test.marketing.activity.api.coupon.common.DS;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class DsAspect 

    // 拦截类上有DS注解的方法调用 没有默认用活动的数据库,所以优惠券的一定要写
    @Around("@within(com.test.marketing.activity.api.coupon.common.DS)")
    public Object dsAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable 
        DS ds = (DS) proceedingJoinPoint.getSignature().getDeclaringType().getAnnotation(DS.class);
        try 
            // 写入线程上下文,应该用哪个DB 没有取到用活动数据库
            DSTypeContainer.setDataBaseType(ds == null ? DBSource.activity.name() : ds.value().name());
            return proceedingJoinPoint.proceed();
         finally 
            // 清空上下文信息
            DSTypeContainer.clearDataBaseType();
        
    


package com.test.marketing.activity.config;

import com.test.marketing.activity.api.coupon.common.DBSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

//@Data
//yml格式的配置文件可以用这个注解
//@ConfigurationProperties(prefix = "spring.datasource")
@Component
@Slf4j
public class DSProperties 
    //活动数据库
    @Value("$spring.datasource.coupon.jdbc-url")
    private String jdbcUrl;
    @Value("$spring.datasource.coupon.driver-class-name")
    private String driverClassName;
    @Value("$spring.datasource.coupon.username")
    private String username;
    @Value("$spring.datasource.coupon.password")
    private String password;

    //优惠券数据库
    @Value("$spring.datasource.activity.jdbc-url")
    private String activityjdbcUrl;
    @Value("$spring.datasource.activity.driver-class-name")
    private String activitydriverClassName;
    @Value("$spring.datasource.activity.username")
    private String activityusername;
    @Value("$spring.datasource.activity.password")
    private String activitypassword;

    public static Map<String, DataSourceProperties> datasource = new HashMap<>(2);

    public Map<String, DataSourceProperties> getDatasource() 
        if (!datasource.isEmpty()) 
            return datasource;
        
        // 活动数据库
        DataSourceProperties activity = new DataSourceProperties();
        activity.setUrl(activityjdbcUrl);
        activity.setDriverClassName(activitydriverClassName);
        activity.setUsername(activityusername);
        activity.setPassword(activitypassword);
        datasource.put(DBSource.activity.name(), activity);
        //优惠券数据库
        DataSourceProperties coupon = new DataSourceProperties();
        coupon.setUrl(jdbcUrl);
        coupon.setDriverClassName(driverClassName);
        coupon.setUsername(username);
        coupon.setPassword(password);
        datasource.put(DBSource.coupon.name(), coupon);

        return datasource;
    

    public void setDatasource(Map<String, DataSourceProperties> datasource) 
        this.datasource = datasource;
    


package com.test.marketing.activity.config;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DSTypeContainer 
    private static final ThreadLocal<String> TYPE = new ThreadLocal<String>();

    public static String defaultType;

    /**
     * 往当前线程里设置数据源类型
     *
     * @param dataBase
     */
    public static void setDataBaseType(String dataBase) 
        if (StrUtil.isNotEmpty(dataBase)) 
            defaultType = dataBase;
        
        TYPE.set(dataBase);
        log.warn("[将当前数据源改为]:" + dataBase);
    

    /**
     * 获取数据源类型
     *
     * @return
     */
    public static String getDataBaseType() 
        String database = TYPE.get();
        log.warn("[获取当前数据源的类型为]:" + database);
        if (StrUtil.isEmpty(database)) 
            database = "activity";
        
        return database;
    

    /**
     * 清空数据类型
     */
    public static void clearDataBaseType() 
        TYPE.remove();
    


package com.test.marketing.activity.config;

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

public class DynamicDataSource extends AbstractRoutingDataSource 

    @Override
    protected Object determineCurrentLookupKey() 
        String dataBaseType = DSTypeContainer.getDataBaseType();
        return dataBaseType;
    



package com.test.marketing.activity.config;

import com.test.marketing.activity.api.coupon.common.DBSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Configuration
//yml格式的配置可以用这个注解
//@EnableConfigurationProperties(DSProperties.class)
@MapperScan(basePackages = "com.test.marketing.activity.dao",
        sqlSessionFactoryRef = "SqlSessionFactory")
public class DynamicDataSourceConfig 

    @Value("$mybatis.mapper-locations")
    private String mapperLocation;

    @Autowired
    private DSProperties dsProperties;

    @SuppressWarnings("unchecked")
    @Bean(name = "datasource")
    public DynamicDataSource DataSource() 
        Map targetDataSource = new HashMap<>(8);
        dsProperties.getDatasource().forEach((k, v) -> 
            targetDataSource.put(k, v.initializeDataSourceBuilder().build()以上是关于springBoot+mybatis多数据源配置的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot入门之基于Druid配置Mybatis多数据源

springboot+mybatis多数据源配置

springBoot+mybatis多数据源配置

SpringBoot2 + Druid + Mybatis 多数据源配置

springboot:mybatis配置多数据源

springboot 整合 mybatis 多数据源配置