Mybatis annotation to separate reading and writing from multiple data sources

First, you need to create two libraries for testing. I use master here_ Test and slave_ Test two libraries, both of which have the same table (lazy, happy) and table structure

Table name t_ user

Two different data are added to the table to facilitate the test

The master database record name is Xiaobin and the slave database record name is Xiaoliu

Start using spring boot to integrate mybatis. First, introduce POM files

  <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.4.RELEASE</version>
  </parent>
  <groupId>com.xiaobin</groupId>
  <artifactId>MysqL_master_slave</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <java.version>1.8</java.version>
    <lombok.version>1.18.6</lombok.version>
    <mybatis.version>1.3.2</mybatis.version>
    <lom@R_830_2419@.version>1.18.6</lom@R_830_2419@.version>
  </properties>

  <dependencies>
    <!-- 添加web启动坐标 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 添加lombok工具坐标 -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>${lombok.version}</version>
    </dependency>
    <!-- 添加springboot 测试坐标 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <!-- 添加lom@R_830_2419@ 测试坐标 -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>${lom@R_830_2419@.version}</version>
    </dependency>
    <!-- 添加mybatis依赖坐标 -->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>${mybatis.version}</version>
    </dependency>
    <!-- 添加MysqL驱动器坐标 -->
    <dependency>
      <groupId>MysqL</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <!-- 添加druid数据源坐标 -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid-spring-boot-starter</artifactId>
      <version>1.1.10</version>
    </dependency>
    <!-- 添加AOP坐标 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

  </dependencies>
</project>

Dynamic data source configuration

The data source used here is Druid, which realizes the switching between data sources. Use @ datasource custom annotation and configure AOP to switch

application. YML profile

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
     xiaobin-master: # 主数据源
      driverClassName: com.MysqL.jdbc.Driver
      username: root
      password: root
      url: jdbc:MysqL://localhost:3306/master_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
     xiaobin-slave: # 从数据源
      driverClassName: com.MysqL.jdbc.Driver
      username: root
      password: root
      url: jdbc:MysqL://localhost:3306/slave_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
mybatis:
 mapper-locations: classpath:mapper/*.xml

Multi data source configuration class

package com.xiaobin.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
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.stereotype.Component;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 创建时间: 2019/9/22 11:42
 * 备注:多数据源配置信息
 * 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
 **/

@Configuration
@Component
public class DynamicDataSourceConfig {

  @Bean
  @ConfigurationProperties("spring.datasource.druid.xiaobin-master")
  public DataSource xiaobinMasterDataSource(){
    return DruidDataSourceBuilder.create().build();
  }

  @Bean
  @ConfigurationProperties("spring.datasource.druid.xiaobin-slave")
  public DataSource xiaobinSlaveDataSource(){
    return DruidDataSourceBuilder.create().build();
  }

  @Bean
  @Primary
  public DynamicDataSource dataSource(DataSource xiaobinMasterDataSource,DataSource xiaobinSlaveDataSource) {
    Map<Object,Object> targetDataSources = new HashMap<>();
    targetDataSources.put("xiaobin-master",xiaobinMasterDataSource);
    targetDataSources.put("xiaobin-slave",xiaobinSlaveDataSource);
    return new DynamicDataSource(xiaobinMasterDataSource,targetDataSources);
  }

}

Dynamic data source switching class

package com.xiaobin.config;

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

import javax.sql.DataSource;
import java.util.Map;

/**
 * 创建时间: 2019/9/22 11:51
 * 备注:动态数据源
 * 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
 **/

public class DynamicDataSource extends AbstractRoutingDataSource {

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

  public DynamicDataSource(DataSource defaultTargetDataSource,Map<Object,Object> targetDataSources) {
    super.setDefaultTargetDataSource(defaultTargetDataSource);
    super.setTargetDataSources(targetDataSources);
    super.afterPropertiesSet();
  }

  @Override
  protected Object determineCurrentLookupKey() {
    return getDataSource();
  }

  public static void setDataSource(String dataSource) {
    contextHolder.set(dataSource);
  }

  public static String getDataSource() {
    return contextHolder.get();
  }

  public static void clearDataSource() {
    contextHolder.remove();
  }
}

Custom @ datasource annotation

Add this annotation to Dao that needs to switch data

package com.xiaobin.annotation;

import java.lang.annotation.*;

/**
 * 创建时间: 2019/9/22 11:53
 * 备注:自定义数据源选择注解
 * 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
 **/

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
  String name() default "";
}

AOP section class configuration

package com.xiaobin.aspect;

import com.xiaobin.annotation.DataSource;
import com.xiaobin.config.DynamicDataSource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 创建时间: 2019/9/22 11:54
 * 备注:
 * 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
 **/

@Aspect
@Component
public class DataSourceAspect {

  @pointcut("@annotation(com.xiaobin.annotation.DataSource)")
  public void dataSourcepointcut() {

  }

  @Around("dataSourcepointcut()")
  public Object around(ProceedingJoinPoint point) throws Throwable {
    MethodSignature signature = (MethodSignature) point.getSignature();
    Method method = signature.getmethod();

    DataSource dataSource = method.getAnnotation(DataSource.class);
    if(dataSource == null){
      DynamicDataSource.setDataSource("xiaobin-master");
    }else {
      DynamicDataSource.setDataSource(dataSource.name());
    }

    try {
      return point.proceed();
    } finally {
      DynamicDataSource.clearDataSource();
    }
  }
}

Start the configuration annotation information, which is important (otherwise an error will be reported during operation)

package com.xiaobin;

import com.xiaobin.config.DynamicDataSourceConfig;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Import;

/**
 * 创建时间: 2019/9/22 11:17
 * 备注:
 * 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
 **/

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@MapperScan(basePackages = "com.xiaobin.mapper")
@Import({DynamicDataSourceConfig.class})
public class StartApp {
  public static void main(String[] args) {
    SpringApplication.run(StartApp.class);
  }
}

Test controller

package com.xiaobin.api;

import com.xiaobin.Entity.TUser;
import com.xiaobin.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 创建时间: 2019/9/22 12:08
 * 备注:
 * 码农自学交流小群:260532022,欢迎大家的加入,分享学习是一件开心事
 **/

@RestController
@RequestMapping
public class UserController {

  @Autowired
  private UserMapper userMapper;

  @GetMapping("/{name}/list")
  public List<TUser> list(@PathVariable("name")String name){
    if(name.equals("master")){
      return userMapper.queryAllWithMaster();
    }else{
      return userMapper.queryAllWithSlave();
    }
  }
}

design sketch

More path value transfer, master-slave data source switching

directory structure

Source address (the database needs to be created by yourself) https://gitee.com/MyXiaoXiaoB...

summary

The above is the whole content of this article. I hope the content of this article has a certain reference value for your study or work. Thank you for your support.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>