SpringBoot整合MyBatis和Druid实现多数据源

在实际开发中,经常会遇到一个应用中可能需要访问多个数据库的情况,典型的使用场景如下:

  1. 业务复杂,数据量大,需要使用多个数据库
  2. 读写分离,提升系统性能

1. 数据库准备

新建两个数据库dynamic-master和dynamic-slave,在master库中新建customer表,slave库中新建orders表

CREATE TABLE `customer`  (
  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `customer_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户名称',
  `sex` tinyint(1) NOT NULL DEFAULT 0 COMMENT '性别 0:为止;1:男;2:女',
  `age` tinyint(2) NOT NULL DEFAULT 0 COMMENT '年龄',
  `phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',
  `deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标识 0:未删除;1:已删除',
  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '客户表' ROW_FORMAT = Dynamic;
CREATE TABLE `orders`  (
  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `order_code` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '订单编码',
  `order_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '订单状态 0:未支付;1:支付中;2:已支付',
  `product_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称',
  `customer_id` bigint(20) NULL DEFAULT NULL COMMENT '客户ID',
  `deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标识 0:未删除;1:已删除',
  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '订单表' ROW_FORMAT = Dynamic;

2. 引入核心依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.9</version>
</dependency>

3. application.yml配置

server:
  port: 8126
spring:
  application:
    name: springboot-dynamic-mybatis
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    master:
      url: jdbc:mysql://localhost:3306/dynamic-master?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    slave:
      url: jdbc:mysql://localhost:3306/dynamic-slave?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    druid:
      initial-size: 5 #初始连接数
      max-active: 20 #最大连接池
      max-wait: 6000 #最大等待时长,毫秒
      min-idle: 1 #最小连接池
      test-while-idle: true #连接时检测
      test-on-borrow: false #申请连接时执行检测
      test-on-return: false #规划连接时执行检测
      validation-query: SELECT 1 FROM DUAL #连接检测
      time-between-eviction-runs-millis: 60000 #检测间隔时间,毫秒
      min-evictable-idle-time-millis: 300000 #连接池最小生存时间,毫秒
      max-evictable-idle-time-millis: 900000 #连接池最大生存时间,毫秒
mybatis:
  mapper-locations: classpath*:/mapper/**/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

4. 数据库配置文件

新建两个配置文件,分别配置master和slave数据库

@Configuration
@MapperScan(basePackages = {"com.xlhj.boot.dynamic.mybatis.mapper.master"}, sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {

    @Primary
    @Bean(name = "masterDataSource")
    @ConfigurationProperties("spring.datasource.master")
    public DataSource dataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Primary
    @Bean(name = "masterTransactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource());
    }

    @Primary
    @Bean(name = "masterSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/master/*.xml"));
        return factoryBean.getObject();
    }

    @Primary
    @Bean(name = "masterSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

@Configuration
@MapperScan(basePackages = {"com.xlhj.boot.dynamic.mybatis.mapper.slave"}, sqlSessionFactoryRef = "slaveSqlSessionFactory")
public class SlaveDataSourceConfig {

    @Bean(name = "slaveDataSource")
    @ConfigurationProperties("spring.datasource.slave")
    public DataSource dataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "slaveTransactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("slaveDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Primary
    @Bean(name = "slaveSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/slave/*.xml"));
        return factoryBean.getObject();
    }

    @Primary
    @Bean(name = "slaveSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("slaveSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

后记

以上方案虽然实现了多数据,但每多一个数据源就需要新增配置文件,还需要分别新建mapper文件,spring-jdbc提供了AbstractRoutingDataSource抽象类,可以实现动态访问数据库。有需要了解这方面知识的小伙伴可以参阅SpringBoot集成AbstractRoutingDataSource实现动态切换多数据源

本文转自 https://blog.csdn.net/liu320yj/article/details/124404950,如有侵权,请联系删除。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot是一个高效的Java开发框架,它能够方便开发者集成MyBatis-Plus实现多数据源的动态切换以及支持分页查询。MyBatis-Plus是一种优秀的ORM框架,它增强了MyBatis的基础功能,并支持通过注解方式进行映射。 首先,我们需要在pom.xml文件中添加MyBatis-Plus和数据库连接池的依赖。在application.yml文件中,我们需要配置多个数据源和对应的连接信息。我们可以定义一个DataSourceConfig用于获取多个数据源,然后在Mapper配置类中使用@MapperScan(basePackages = {"com.test.mapper"})来扫描Mapper接口。 要实现动态切换数据源,我们可以自定义一个注解@DataSource来标注Mapper接口或方法,然后使用AOP拦截数据源切换,实现动态切换。在实现分页查询时,我们可以使用MyBatis-Plus提供的分页插件来支持分页查询。 代码示例: 1. 在pom.xml文件中添加MyBatis-Plus和数据库连接池的依赖。 ``` <dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.4</version> </dependency> </dependencies> ``` 2. 在application.yml文件中配置多个数据源和对应的连接信息。以两个数据源为例: ``` spring: datasource: druid: db1: url: jdbc:mysql://localhost:3306/db1 username: root password: root driver-class-name: com.mysql.jdbc.Driver db2: url: jdbc:mysql://localhost:3306/db2 username: root password: root driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource # 指定默认数据源 primary: db1 ``` 3. 定义一个DataSourceConfig用于获取多个数据源。 ``` @Configuration public class DataSourceConfig { @Bean("db1") @ConfigurationProperties("spring.datasource.druid.db1") public DataSource dataSource1() { return DruidDataSourceBuilder.create().build(); } @Bean("db2") @ConfigurationProperties("spring.datasource.druid.db2") public DataSource dataSource2() { return DruidDataSourceBuilder.create().build(); } @Bean @Primary public DataSource dataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); // 设置数据源映射关系 Map<Object, Object> dataSourceMap = new HashMap<>(); dataSourceMap.put("db1", dataSource1()); dataSourceMap.put("db2", dataSource2()); dynamicDataSource.setTargetDataSources(dataSourceMap); // 设置默认数据源 dynamicDataSource.setDefaultTargetDataSource(dataSource1()); return dynamicDataSource; } } ``` 4. 在Mapper配置类中使用@MapperScan(basePackages = {"com.test.mapper"})来扫描Mapper接口,并使用@DataSource注解来标注Mapper接口或方法。 ``` @Configuration @MapperScan(basePackages = {"com.test.mapper"}) public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } } @DataSource("db1") public interface UserMapper { @Select("select * from user where id = #{id}") User selectById(@Param("id") Long id); } ``` 5. 实现AOP拦截数据源切换。 ``` @Aspect @Component public class DataSourceAspect { @Before("@annotation(ds)") public void beforeSwitchDataSource(JoinPoint point, DataSource ds) { String dataSource = ds.value(); if (!DynamicDataSourceContextHolder.containDataSourceKey(dataSource)) { System.err.println("数据源 " + dataSource + " 不存在,使用默认数据源"); } else { System.out.println("使用数据源:" + dataSource); DynamicDataSourceContextHolder.setDataSourceKey(dataSource); } } } ``` 6. 分页查询的使用示例: ``` @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override @DataSource("db1") public IPage<User> getUserList(int pageNum, int pageSize) { Page<User> page = new Page<>(pageNum, pageSize); return userMapper.selectPage(page, null); } } ``` 以上就是SpringBoot整合MyBatis-Plus实现多数据源的动态切换和分页查询的具体实现过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值