Springboot combat code series [integrated mybatis-plus and druid to achieve multi-data source switching]

Springboot combat code series [integrated mybatis-plus and druid to achieve multi-data source switching]

Why write this article?

  1. The official document is not detailed enough, the following is a version that can be read and used
  2. Mainly also convenient for you to refer to the code in the future, no more searching

The version of springboot used in this article: 2.2.6.RELEASE

Add dependency

Check out the latest version of the plugin: https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter

The latest version of the druid plug-in should also be viewed : https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter
But here, it is recommended to see the version of druid supported by mybatis plus.

	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<optional>true</optional>
	</dependency>

	<!--@DS注解需要的依赖-->
	<dependency>
		<groupId>com.baomidou</groupId>
		<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
		<version>3.0.0</version>
	</dependency>
	<dependency>
		<groupId>com.baomidou</groupId>
		<artifactId>mybatis-plus-boot-starter</artifactId>
		<version>3.3.1</version>
	</dependency>
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid-spring-boot-starter</artifactId>
		<version>1.1.21</version>
	</dependency>
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<scope>runtime</scope>
	</dependency>

Configuration file

First, remove the Druid auto-configuration class:

@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)

Some versions of springBoot may not be excluded above but can be excluded in the following ways.

spring:
  autoconfigure:
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure

Reason: DruidDataSourceAutoConfigure will inject a DataSourceWrapper, which will find url, username, password, etc. under the native spring.datasource. And the configuration path of our dynamic data source is changing.

Then the following is a very simple druid configuration (the appendix has the complete configuration):

spring:
  datasource:
    dynamic:
	  # 默认源
      primary: druid-admin
      druid:
        #初始化大小,最小,最大
        initial-size: 5
        min-idle: 5
        max-active: 20
      datasource:
        # 数据源1
        druid-admin:
          url: jdbc:mysql://IP:3306/db_admin?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
          username: xxx
          password: xxx
          driver-class-name: com.mysql.cj.jdbc.Driver
        # 数据源2
        druid-web:
          url: jdbc:mysql://IP:3306/db_web?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
          username: xxx
          password: xxx
          driver-class-name: com.mysql.cj.jdbc.Driver

Code

Because you need to use pagination query test, so add paging plugin

    /**
     * 分页插件,解决分页时total=0问题
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

Prepare entity class

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("t_user")
public class User {
    @TableId(type = IdType.AUTO)
    private Integer id;
    @TableField(value = "user_name")
    private String username;
    private String password;
    private String email;
}

@Data
@TableName("role")
public class Role {
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String name;
}

Prepare mapper

Just need to inherit the BaseMappercommonly used CRUD interface method, plus the @Mapperannotation mark

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jimo.mybatisplusdruiddemo.model.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

@Mapper
public interface RoleMapper extends BaseMapper<Role> {
}

Write service layer

Just inherit ServiceImpl.

The @DScomment here is to select the data source, the name corresponds to the configuration

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jimo.mybatisplusdruiddemo.mapper.UserMapper;
import com.jimo.mybatisplusdruiddemo.model.User;
import org.springframework.stereotype.Service;

@Service
@DS("druid-web")
public class UserService extends ServiceImpl<UserMapper, User> {
}

/**
* 因为默认就是druid-admin库,所以,可以省略,加上也没关系
*/
@Service
//@DS("druid-admin")
public class RoleService extends ServiceImpl<RoleMapper, Role> {
}

test

The test class is very simple, execute a paging query:

@SpringBootTest
class MybatisPlusDruidDemoApplicationTests {

    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;

    @Test
    void testUserService() {
        final int size = 10;
        final Page<User> page = userService.page(new Page<>(1, size));
        assertEquals(size, page.getRecords().size());
        assertTrue(page.getTotal() >= size);
    }

    @Test
    void testRoleService() {
        final int size = 1;
        final Page<Role> page = roleService.page(new Page<>(1, size));
        assertEquals(size, page.getRecords().size());
        assertTrue(page.getTotal() >= size);
    }
}	

You can see the initialization and destruction of the database in the log:

2020-04-01 10:34:20.661  INFO 15600 --- [           main] j.m.MybatisPlusDruidDemoApplicationTests : No active profile set, falling back to default profiles: default
2020-04-01 10:34:22.805  INFO 15600 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1,druid-admin} inited
2020-04-01 10:34:23.118  INFO 15600 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-2,druid-web} inited
2020-04-01 10:34:23.118  INFO 15600 --- [           main] c.b.d.d.DynamicRoutingDataSource         : dynamic-datasource - load a datasource named [druid-admin] success
2020-04-01 10:34:23.119  INFO 15600 --- [           main] c.b.d.d.DynamicRoutingDataSource         : dynamic-datasource - load a datasource named [druid-web] success
2020-04-01 10:34:23.119  INFO 15600 --- [           main] c.b.d.d.DynamicRoutingDataSource         : dynamic-datasource initial loaded [2] datasource,primary datasource named [druid-admin]
 _ _   |_  _ _|_. ___ _ |    _ 
| | |\/|_)(_| | |_\  |_)||_|_\ 
     /               |         
                        3.3.1 
2020-04-01 10:34:24.379  INFO 15600 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-04-01 10:34:24.888  INFO 15600 --- [           main] j.m.MybatisPlusDruidDemoApplicationTests : Started MybatisPlusDruidDemoApplicationTests in 4.695 seconds (JVM running for 6.375)

...

2020-04-01 10:34:56.112  INFO 15600 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
2020-04-01 10:34:56.113  INFO 15600 --- [extShutdownHook] c.b.d.d.DynamicRoutingDataSource         : dynamic-datasource start closing ....
2020-04-01 10:34:56.116  INFO 15600 --- [extShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} closing ...
2020-04-01 10:34:56.126  INFO 15600 --- [extShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} closed
2020-04-01 10:34:56.126  INFO 15600 --- [extShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-2} closing ...
2020-04-01 10:34:56.130  INFO 15600 --- [extShutdownHook] com.alibaba.druid.pool.DruidDataSource   : {dataSource-2} closed
2020-04-01 10:34:56.130  INFO 15600 --- [extShutdownHook] c.b.d.d.DynamicRoutingDataSource         : dynamic-datasource all closed success,bye

to sum up

key emphasis

@DS("druid-web")Annotations are used to select the data source and can be used in the mapper layer

@Mapper
@DS("druid-web")
public interface UserMapper extends BaseMapper<User> {
}

Just like sometimes being lazy and not wanting to write a service layer, you can also switch multiple data sources in mapper:

    @Autowired
    private UserMapper userMapper;

    @Test
    void testUserMapper() {
        final int size = 10;
        final Page<User> page = userMapper.selectPage(new Page<>(1, size), null);
        assertEquals(size, page.getRecords().size());
        assertTrue(page.getTotal() >= size);
    }

appendix

The complete configuration of druid:

spring:
  datasource:
    dynamic:
      primary: druid-admin
      druid:
        #初始化大小,最小,最大
        initial-size: 5
        min-idle: 5
        max-active: 20
        #配置获取连接等待超时的时间
        max-wait: 60000
        #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        time-between-eviction-runs-millis: 60000
        #配置一个连接在池中最小生存的时间,单位是毫秒
        min-evictable-idle-time-millis: 300000
        validation-query: SELECT 1 FROM DUAL
        test-while-idle: true
        test-on-borrow: false
        test-on-return: false
        #打开PSCache,并且指定每个连接上PSCache的大小
        pool-prepared-statements: true
        max-pool-prepared-statement-per-connection-size: 20
        #配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
        filters: stat,wall # 注意这个值和druid原生不一致,默认启动了stat,wall
        filter:
          log4j:
            enabled: true
          wall:
            config:
              # 允许多个语句一起执行
              multi-statement-allow: true
            enabled: true
            db-type: mysql
          stat:
            enabled: true
            db-type: mysql
      datasource:
        # 数据源1
        druid-admin:
          url: jdbc:mysql://IP:3306/db_admin?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
          username: xxx
          password: xxx
          driver-class-name: com.mysql.cj.jdbc.Driver
        # 数据源2
        druid-web:
          url: jdbc:mysql://IP:3306/db_web?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
          username: xxx
          password: xxx
          driver-class-name: com.mysql.cj.jdbc.Driver

reference

  1. https://mybatis.plus/guide/dynamic-datasource.html
  2. https://github.com/baomidou/dynamic-datasource-spring-boot-starter/wiki/Integration-With-Druid
Published 80 original articles · Like 319 · Visits 340,000+

Guess you like

Origin blog.csdn.net/jimo_lonely/article/details/105254359
Recommended