Springboot配置多数据源

日常开发中大家大家都会遇到多数据源切换,下面写一下我的配置情况,供大家参考。
数据源支持 Oracle、Mysql、Sqlserver、presto等
下面使用两个数据库来进行配置 分为A库和B库

下面是搭建步骤
1、先在application.properties配置两个数据源
数据库连接池使用的是Hikari
A库是Oracle B库是mysql

#mybatis
mybatis.mapper-locations= classpath*:mapper/*/*/*.xml
mybatis.typeAliasesPackage= com.pojo
mybatis.configuration.call-setters-on-nulls=true

#A 库
multiple.datasource.A.type=com.zaxxer.hikari.HikariDataSource
multiple.datasource.A.driver-class-name=oracle.jdbc.OracleDriver
multiple.datasource.A.jdbc-url= 
multiple.datasource.A.username= 
multiple.datasource.A.password= 
# 最小空闲连接数量
multiple.datasource.A.minimum-idle=5
# 连接池最大连接数,默认是10
multiple.datasource.A.maximum-pool-size=10
# 此属性控制从池返回的连接的默认自动提mes,默认值:true
multiple.datasource.A.auto-commit=true
# 空闲连接存活最大时间,默认60000mes0分钟)
multiple.datasource.A.idle-timeout=30000
# 连接池名称
multiple.datasource.A.pool-name=AHikariCP
# 此属性控制池中连接的最长生命周期,默认1800000即30分钟
multiple.datasource.A.max-lifetime=1800000
# 数据库连接超时时间,默认30秒,即3mes0
multiple.datasource.A.connection-timeout=30000
multiple.datasource.A.connection-test-query=SELECT 1 FROM DUAL

#B数据库
multiple.datasource.B.type= com.zaxxer.hikari.HikariDataSource
multiple.datasource.B.driver-class-name=com.mysql.cj.jdbc.Driver
multiple.datasource.B.jdbc-url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
multiple.datasource.B.username=
multiple.datasource.B.password=
# 最小空闲连接数量
multiple.datasource.B.minimum-idle=5
# 连接池最大连接数,默认是10
multiple.datasource.B.maximum-pool-size=10
# 此属性控制从池返回的连接的默认自动提交行为,默认值:true
multiple.datasource.B.auto-commit=true
# 空闲连接存活最大时间,默认600000(10分钟)
multiple.datasource.B.idle-timeout=30000
# 连接池名称
multiple.datasource.B.pool-name=BHikariCP
# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
multiple.datasource.B.max-lifetime=1800000
# 数据库连接超时时间,默认30秒,即30000
multiple.datasource.B.connection-timeout=30000
multiple.datasource.B.connection-test-query=SELECT 1 FROM DUAL

2、编写自定义数据源注解 后面通过Spring AOP进行切换

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TargetDataSource {
   //默认A库
    DataSourceKey dataSourceKey() default DataSourceKey.A;
}

3、配置多数据源

public enum DataSourceKey {
        A,
        B
}
public class DynamicDataSourceContextHolder {


    private static final ThreadLocal<DataSourceKey> currentDatesource = new ThreadLocal<>();

    /**
     * 清除当前数据源
     */
    public static void clear() {
        currentDatesource.remove();
    }

    /**
     * 获取当前使用的数据源
     *
     * @return 当前使用数据源的ID
     */
    public static DataSourceKey get() {
        return currentDatesource.get();
    }

    /**
     * 设置当前使用的数据源
     *
     * @param value 需要设置的数据源ID
     */
    public static void set(DataSourceKey value) {
        currentDatesource.set(value);
    }

    /**
     * 设置从A库读取数据
     */
    public static void setA() {
        DynamicDataSourceContextHolder.set(DataSourceKey.A);
    }

    /**
     * 设置从B库读取数据
     */
    public static void setB() {
        DynamicDataSourceContextHolder.set(DataSourceKey.B);
    }
}
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
    private static final Logger LOG = LoggerFactory.getLogger(DynamicRoutingDataSource.class);
    @Override
    protected Object determineCurrentLookupKey() {
        LOG.info("当前数据源:"+ DynamicDataSourceContextHolder.get());
        return DynamicDataSourceContextHolder.get();
    }
}
@Configuration
public class DynamicDataSourceConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "multiple.datasource.A")
    public DataSource dbA() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "multiple.datasource.B")
    public DataSource dbB() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 核心动态数据源
     *
     * @return 数据源实例
     */
    @Bean
    public DataSource dynamicDataSource() {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
        dataSource.setDefaultTargetDataSource(dbA());
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put(DataSourceKey.A, dbA());
        dataSourceMap.put(DataSourceKey.B, dbB());        
        dataSource.setTargetDataSources(dataSourceMap);
        return dataSource;
    }

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

    @Value("${mybatis.typeAliasesPackage}")
    private String typeAliasesPackage;

    @Value("${mybatis.configuration.call-setters-on-nulls}")
    private boolean callSettersOnNulls;


    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource());

        //此处设置为了解决找不到mapper文件的问题
        Resource[] resources = new PathMatchingResourcePatternResolver().getResources(mapperLocation);
        sqlSessionFactoryBean.setMapperLocations(resources);
        //POJO
        sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
        //此处设置为了解决  查询数据为null不显示该字段  true显示  false不显示
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setCallSettersOnNulls(callSettersOnNulls);
        sqlSessionFactoryBean.setConfiguration(configuration);

        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory());
    }

    /**
     * 事务管理
     *
     * @return 事务管理实例
     */
    @Bean
    public PlatformTransactionManager platformTransactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}

4、配置切面拦截注解进行数据库切换

@Aspect
@Order(-1)
@Component
public class DynamicDataSourceAspect {
    private static final Logger LOG = LoggerFactory.getLogger(DynamicDataSourceAspect.class);
    /**
     * 执行方法前更换数据源
     *
     * @param joinPoint        切点
     * @param targetDataSource 动态数据源
     */
    @Before("@annotation(targetDataSource)")
    public void doBefore(JoinPoint joinPoint, TargetDataSource targetDataSource) {
        DataSourceKey dataSourceKey = targetDataSource.dataSourceKey();
        DynamicDataSourceContextHolder.set(dataSourceKey);
    }

    /**
     * 执行方法后清除数据源设置
     *
     * @param joinPoint        切点
     * @param targetDataSource 动态数据源
     */
    @After("@annotation(targetDataSource)")
    public void doAfter(JoinPoint joinPoint, TargetDataSource targetDataSource) {
        LOG.info(String.format("当前数据源  %s  执行清理方法", targetDataSource.dataSourceKey()));
        DynamicDataSourceContextHolder.clear();
    }
}

5、在Mapper文件中指定数据源

@Mapper
public interface EquipmentCheckMapper {

    /**
     *  A库读取数据
     * @param 
     * @return
     */
    @TargetDataSource(dataSourceKey = DataSourceKey.A)
    List<Student> getA();
   /**
     *  B库读取数据
     * @param 
     * @return
     */
    @TargetDataSource(dataSourceKey = DataSourceKey.B)
    List<Student> getB();

6、启动类注解也要配置

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableAspectJAutoProxy

至此 多数据的配置工作就完成了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值