mysql druid 多数据源_springboot+druid+mybatis plus的多数据源配置

多数据源配置,在我们集成多个系统或者对接的时候经常会用到,结合springboot、druid提供了比较方便的集成方案。

思路:

1、yml中配置多个数据源信息

2、通过AOP切换不同数据源

3、配合mybatis plus使用

1、yml配置

spring:

aop:

proxy-target-class: true

auto: true

datasource:

druid:

db1:

url: jdbc:mysql://localhost:3306/eboot

username: root

password: root

driver-class-name: com.mysql.jdbc.Driver

initialSize: 5

minIdle: 5

maxActive: 20

db2:

url: jdbc:oracle:thin:@192.168.136.222:ORCL

username: sa

password: sa123456

driver-class-name: oracle.jdbc.OracleDriver

initialSize: 5

minIdle: 5

maxActive: 20

db3:

url: jdbc:oracle:thin:@192.168.136.223:ORCL

username: sb

password: sb123456

driver-class-name: oracle.jdbc.OracleDriver

initialSize: 5

minIdle: 5

maxActive: 20

2、启动加载多个数据源

下面mybatis plus的全局配置被注掉了,因为同样可以在yml中配置也可以

package com.df.openapi.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;

import com.baomidou.mybatisplus.MybatisConfiguration;

import com.baomidou.mybatisplus.entity.GlobalConfiguration;

import com.baomidou.mybatisplus.mapper.LogicSqlInjector;

import com.baomidou.mybatisplus.plugins.PaginationInterceptor;

import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;

import com.df.openapi.config.db.DBTypeEnum;

import com.df.openapi.config.db.DynamicDataSource;

import com.df.openapi.config.db.MyMetaObjectHandler;

import org.apache.ibatis.plugin.Interceptor;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.type.JdbcType;

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.Primary;

import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

import java.util.HashMap;

import java.util.Map;

/**

* @author 小尘哥

*/

@EnableTransactionManagement

@Configuration

@MapperScan("com.df.openapi.**.mapper.db*")

public class MybatisPlusConfig {

@Bean

public PaginationInterceptor paginationInterceptor() {

PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

paginationInterceptor.setLocalPage(true);

return paginationInterceptor;

}

@Bean(name = "db1")

@ConfigurationProperties(prefix = "spring.datasource.druid.db1")

public DataSource db1() {

return DruidDataSourceBuilder.create().build();

}

@Bean(name = "db2")

@ConfigurationProperties(prefix = "spring.datasource.druid.db2")

public DataSource db2() {

return DruidDataSourceBuilder.create().build();

}

@Bean(name = "db3")

@ConfigurationProperties(prefix = "spring.datasource.druid.db3")

public DataSource db3() {

return DruidDataSourceBuilder.create().build();

}

/**

* 动态数据源配置

*

* @return

*/

@Bean

@Primary

public DataSource multipleDataSource(@Qualifier("db1") DataSource db1,

@Qualifier("db2") DataSource db2,

@Qualifier("db3") DataSource db3) {

DynamicDataSource dynamicDataSource = new DynamicDataSource();

Map targetDataSources = new HashMap<>();

targetDataSources.put(DBTypeEnum.db1.getValue(), db1);

targetDataSources.put(DBTypeEnum.db2.getValue(), db2);

targetDataSources.put(DBTypeEnum.db3.getValue(), db3);

dynamicDataSource.setTargetDataSources(targetDataSources);

dynamicDataSource.setDefaultTargetDataSource(db2);

return dynamicDataSource;

}

@Bean("sqlSessionFactory")

public SqlSessionFactory sqlSessionFactory() throws Exception {

MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();

sqlSessionFactory.setDataSource(multipleDataSource(db1(), db2(),db3()));

MybatisConfiguration configuration = new MybatisConfiguration();

configuration.setJdbcTypeForNull(JdbcType.NULL);

configuration.setMapUnderscoreToCamelCase(true);

configuration.setCacheEnabled(false);

sqlSessionFactory.setConfiguration(configuration);

//PerformanceInterceptor(),OptimisticLockerInterceptor()

//添加分页功能

sqlSessionFactory.setPlugins(new Interceptor[]{

paginationInterceptor()

});

// sqlSessionFactory.setGlobalConfig(globalConfiguration());

return sqlSessionFactory.getObject();

}

/* @Bean

public GlobalConfiguration globalConfiguration() {

GlobalConfiguration conf = new GlobalConfiguration(new LogicSqlInjector());

conf.setLogicDeleteValue("-1");

conf.setLogicNotDeleteValue("1");

conf.setIdType(0);

conf.setMetaObjectHandler(new MyMetaObjectHandler());

conf.setDbColumnUnderline(true);

conf.setRefresh(true);

return conf;

}*/

}

3、DBType枚举类

package com.df.openapi.config.db;

public enum DBTypeEnum {

db1("db1"), db2("db2"), db3("db3");

private String value;

DBTypeEnum(String value) {

this.value = value;

}

public String getValue() {

return value;

}

}

4、动态数据源决策

package com.df.openapi.config.db;

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

public class DynamicDataSource extends AbstractRoutingDataSource {

@Override

protected Object determineCurrentLookupKey() {

return DbContextHolder.getDbType();

}

}

5、设置、获取数据源

package com.df.openapi.config.db;

public class DbContextHolder {

private static final ThreadLocal contextHolder = new ThreadLocal<>();

/**

* 设置数据源

* @param dbTypeEnum

*/

public static void setDbType(DBTypeEnum dbTypeEnum) {

contextHolder.set(dbTypeEnum.getValue());

}

/**

* 取得当前数据源

* @return

*/

public static String getDbType() {

return (String) contextHolder.get();

}

/**

* 清除上下文数据

*/

public static void clearDbType() {

contextHolder.remove();

}

}

6、AOP实现的数据源切换

@Order设置的足够小是为了让他先执行

package com.df.openapi.config.db;

import lombok.extern.slf4j.Slf4j;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.springframework.core.annotation.Order;

import org.springframework.stereotype.Component;

/**

* @author 迪富

*/

@Component

@Order(value = -100)

@Slf4j

@Aspect

public class DataSourceSwitchAspect {

@Pointcut("execution(* com.df.openapi.*.mapper.db1..*.*(..))")

private void db1Aspect() {

}

@Pointcut("execution(* com.df.openapi.*.mapper.db2..*.*(..))")

private void db2Aspect() {

}

@Pointcut("execution(* com.df.openapi.*.mapper.db3..*.*(..))")

private void db3Aspect() {

}

@Before("db1Aspect()")

public void db1() {

log.info("切换到db1 数据源...");

DbContextHolder.setDbType(DBTypeEnum.db1);

}

@Before("db2Aspect()")

public void db2() {

log.info("切换到db2 数据源...");

DbContextHolder.setDbType(DBTypeEnum.db2);

}

@Before("db3Aspect()")

public void db3() {

log.info("切换到db3 数据源...");

DbContextHolder.setDbType(DBTypeEnum.db3);

}

}

7、mapper层结构

ff5af6c59365?utm_source=oschina-app

根据dbx的实现数据源切换.png

8、写一个service测试一下

可以看到下面的两个Mapper分别来自db1和db2

package com.df.openapi.system.service.impl;

import com.df.openapi.system.entity.PtDict;

import com.df.openapi.system.entity.SysDict;

import com.df.openapi.system.mapper.db1.PtDictMapper;

import com.df.openapi.system.mapper.db2.SysDictMapper;

import com.df.openapi.system.service.IDictService;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service

public class DictServiceImpl implements IDictService {

@Resource

private PtDictMapper ptDictMapper;

@Resource

private SysDictMapper sysDictMapper;

@Override

public void getById(String id) {

PtDict dict = ptDictMapper.selectById("2bf6257fc8fe483c84c1ad7e89d632f6");

SysDict sysDict = sysDictMapper.getById("49");

System.out.println("123");

}

}

9、简单的单元测试

@RunWith(SpringRunner.class)

@SpringBootTest

public class OpenApiApplicationTests {

@Autowired

private IDictService dictService;

@Test

public void contextLoads() {

}

@Test

public void test() {

dictService.getById("1");

}

}

10、测试结果

ff5af6c59365?utm_source=oschina-app

取到两个数据库的数据.png

参考上面的方法,可以随意配置三四五六七八九十个数据源都没问题,有问题欢迎随时来撩!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值