Mybatis-plus配置多数据源,连接多数据库方式

 更新时间:2024年06月14日 09:08:39   作者:Cz范特西  
这篇文章主要介绍了Mybatis-plus配置多数据源,连接多数据库方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

前言

工作的时候,遇到了需要将一个数据库的一些数据插入或更新到另一个数据库。

一开始使用

insert into TABLE (col1,col2) VALUES (val1,val2) ON DUPLICATE KEY update col1 = "val1"; 

(这句sql语句的意思是:将val1,val2值插入到TABLE表的col1和col2字段中,如果出现主键或唯一冲突,就进行更新,只将col1值更新为val1)进行数据的插入和更新。

但是每次都要对着这一条sql语句进行修改,十分麻烦,就想着能否同时连接两个数据库进行业务处理。

业务逻辑

使用Mybatis实现

首先,如果你的项目用的是Mybatis,那么以下配置可以实现配置多数据源,连接多数据库的作用。但是,如果你使用的是Mybatis-plus,本人建议使用Mybatis-plus实现更加简单易操作。

1、在yml配置文件中配置多数据库

例如:

spring:
  application:
    name: CONNECTION
  datasource:
    db1:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
      username: root
      password: 123456
      type: com.alibaba.druid.pool.DruidDataSource
    db2:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://11.11.11.11:3306/test?serverTimezone=UTC
      username: root
      password: 654321
      type: com.alibaba.druid.pool.DruidDataSource

注意,将数据库配置中的url改为jdbc-url,否则无法配置多数据源。

2、创建不同的mapper,用于不同的数据库

3、编写数据源的配置类

例如:

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.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
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;

@Configuration
@MapperScan(basePackages = "com.czf.connect.mapper.db1", sqlSessionTemplateRef  = "db1SqlSessionTemplate")
//此处的basePackages指向的是你存放数据库db1的mapper的包
public class DataSource1Config {

    @Bean(name = "db1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.db1")//指向yml配置文件中的数据库配置
    @Primary    //主库加这个注解,修改优先权,表示发现相同类型bean,优先使用该方法。
    public DataSource dbDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "db1SqlSessionFactory")
    @Primary
    public SqlSessionFactory dbSqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*xml"));
        //这个的getResources指向的是你的mapper.xml文件,相当于在yml中配置的mapper-locations,此处配置了yml中就不用配置,或者说不会读取yml中的该配置。
        return bean.getObject();
    }

    @Bean(name = "db1TransactionManager")
    @Primary
    public DataSourceTransactionManager dbTransactionManager(@Qualifier("db1DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "db1SqlSessionTemplate")
    @Primary
    public SqlSessionTemplate dbSqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

数据库db2的配置类:

@Configuration
@MapperScan(basePackages = "com.czf.connect.mapper.db2", sqlSessionTemplateRef  = "db2SqlSessionTemplate")
public class DataSource2Config {

    @Bean(name = "db2DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.db2")
    public DataSource dbDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "db2SqlSessionFactory")
    public SqlSessionFactory dbSqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*xml"));
        return bean.getObject();
    }

    @Bean(name = "db2TransactionManager")
    public DataSourceTransactionManager dbTransactionManager(@Qualifier("db2DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "db2SqlSessionTemplate")
    public SqlSessionTemplate dbSqlSessionTemplate(@Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

整体结构:

在这里插入图片描述

至此,需要修改或查询哪个数据库,只需要在对应的com///mapper/db包中创建对应的mapper类或者编写特定的sql语句即可。

使用Mybatis-plus实现

Mybatis-plus官网很清楚的告诉了我们如何配置多数据源。

1、引入dynamic-datasource-spring-boot-starter

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  <version>${version}</version>
</dependency>

2、配置数据源

spring:
  datasource:
    dynamic:
      primary: mysql1 #设置默认的数据源或者数据源组,默认值即为mysql1
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        mysql1:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        mysql2:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        mysql2:
          url: ENC(xxxxx) # 内置加密,使用请查看详细文档
          username: ENC(xxxxx)
          password: ENC(xxxxx)
          driver-class-name: com.mysql.jdbc.Driver
       #......省略

3、使用 @DS 切换数据源

@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解

注解结果
没有@DS默认数据源
@DS(“dsName”)dsName可以为组名也可以为具体某个库的名称
@Service
@DS("mysql1")
public class UserServiceImpl implements UserService {

  @Autowired
  private JdbcTemplate jdbcTemplate;

  public List selectAll() {
    return  jdbcTemplate.queryForList("select * from user");
  }
  
  @Override
  @DS("mysql2")
  public List selectByCondition() {
    return  jdbcTemplate.queryForList("select * from user where age >10");
  }
}

在这里会有个小问题,假如我编写了两个方法,方法A使用的是 @DS(“mysql1”) ,功能是查询mysql1中的数据;方法B调用的是@DS(“mysql2”),是将数据插入到mysql2数据库中,那么我想在方法B中调用方法A,实现mysql1中查询的数据插入到mysql2中,能够成功吗?

答案是:不可以。

要想实现这个功能,我们可以使用多数据源的一个类,简单来说是一个队列,将需要使用到的数据源push进行,不用时再poll掉。就不用使用@DS注解了。

比如:

@RequestMapping("/Bmetohd")
public int Bmethod(){
    DynamicDataSourceContextHolder.push("mysql1");
    List<User> users = Amethod();
    DynamicDataSourceContextHolder.poll();
    DynamicDataSourceContextHolder.push("mysql2");
    int num = 0;
    for(User user: users){
        int i = User2Mapper.insert(user);
        num += i;
    }
    DynamicDataSourceContextHolder.poll();
    return num;
}

重点:

DynamicDataSourceContextHolder.push("mysql1");
//业务代码
DynamicDataSourceContextHolder.poll();

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • jvm双亲委派 vs 破坏双亲委派理解加载器的权责分配

    jvm双亲委派 vs 破坏双亲委派理解加载器的权责分配

    这篇文章主要为大家介绍了jvm双亲委派 vs 破坏双亲委派对比来理解加载器的权责分配,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • springboot 注解方式批量插入数据的实现

    springboot 注解方式批量插入数据的实现

    一次请求需要往数据库插入多条数据时,可以节省大量时间,本文主要介绍了springboot 注解方式批量插入数据,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Spring中的动态数据源解读

    Spring中的动态数据源解读

    这篇文章主要介绍了关于Spring中的动态数据源解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Spring Data Jpa返回自定义对象的3种方法实例

    Spring Data Jpa返回自定义对象的3种方法实例

    在使用Spring Data Jpa框架时,根据业务需求我们通常需要进行复杂的数据库查询,下面这篇文章主要给大家介绍了关于Spring Data Jpa返回自定义对象的3种方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • SpringBoot中的@ConfigurationProperties注解解析

    SpringBoot中的@ConfigurationProperties注解解析

    这篇文章主要介绍了SpringBoot中的@ConfigurationProperties注解解析,Spring源码中大量使用了ConfigurationProperties注解,通过与其他注解配合使用,能够实现Bean的按需配置,该注解可以放在类上,也可以放在方法上,需要的朋友可以参考下
    2023-11-11
  • java写入文件的几种方法分享

    java写入文件的几种方法分享

    这篇文章主要介绍了java写入文件的几种方法,需要的朋友可以参考下
    2014-02-02
  • 深入理解Java中的装箱和拆箱

    深入理解Java中的装箱和拆箱

    这篇文章主要介绍了深入理解Java中的装箱和拆箱,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • 基于@RequestBody和@ResponseBody及Stringify()的作用说明

    基于@RequestBody和@ResponseBody及Stringify()的作用说明

    这篇文章主要介绍了基于@RequestBody和@ResponseBody及Stringify()的作用说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Mybatis 查询语句条件为枚举类型时报错的解决

    Mybatis 查询语句条件为枚举类型时报错的解决

    这篇文章主要介绍了Mybatis 查询语句条件为枚举类型时报错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java使用嵌套循环模拟ATM机取款业务操作示例

    Java使用嵌套循环模拟ATM机取款业务操作示例

    这篇文章主要介绍了Java使用嵌套循环模拟ATM机取款业务操作,结合实例形式分析了Java模拟ATM机取款业务操作的相关流程控制、数值判断等操作技巧,需要的朋友可以参考下
    2019-11-11

最新评论