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多数据源