多数据源切换

多数据源切换

  • 1.jdbcTemplate
  • 2.使用切面
  • 3.mybatis层次的多数据源
  • 4.spring的dynamic自动注入

项目中经常会有多个数据源,那么如何处理呢
有4种方法
准备:
创建两个数据库

CREATE SCHEMA `test` DEFAULT CHARACTER SET utf8mb4 ;
CREATE SCHEMA `school` DEFAULT CHARACTER SET utf8mb4 ;

test数据库创建user表,school数据库创建student表

--
-- Table structure for table `user`
--

DROP TABLE IF EXISTS `user`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(100) NOT NULL COMMENT '用户名',
  `real_name` varchar(200) DEFAULT NULL COMMENT '真实姓名',
  `password` varchar(2000) NOT NULL COMMENT '密码',
  `sex` tinyint(1) NOT NULL COMMENT '性别:0-男,1-女',
  `birthday` date NOT NULL COMMENT '生日',
  `card_id` varchar(20) NOT NULL COMMENT '身份证号',
  `phone` varchar(20) NOT NULL COMMENT '手机号',
  PRIMARY KEY (`id`),
  UNIQUE KEY `card_id` (`card_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `user`
--

LOCK TABLES `user` WRITE;
/*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` VALUES (1,'liming','黎明','123456',1,'2000-09-09','623001200010014433','13099890032'),(3,'miaoshanshan','苗姗姗','123456',0,'2001-10-12','314002200110125523','13509327765');
/*!40000 ALTER TABLE `user` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Host: localhost    Database: school
-- ------------------------------------------------------
-- Server version	8.0.29

--
-- Table structure for table `student`
--

DROP TABLE IF EXISTS `student`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `student` (
  `id` int NOT NULL AUTO_INCREMENT,
  `student_name` varchar(100) NOT NULL COMMENT '学生姓名',
  `student_no` varchar(20) DEFAULT NULL COMMENT '学号',
  `password` varchar(200) NOT NULL COMMENT '密码',
  `sex` tinyint(1) NOT NULL COMMENT '性别:0-男,1-女',
  `birthday` date NOT NULL COMMENT '生日',
  `card_id` varchar(20) NOT NULL COMMENT '身份证号',
  PRIMARY KEY (`id`),
  UNIQUE KEY `student_no` (`student_no`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='学生表';
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `student`
--

LOCK TABLES `student` WRITE;
/*!40000 ALTER TABLE `student` DISABLE KEYS */;
INSERT INTO `student` VALUES (1,'黎明','202110010101','123456',1,'2000-09-09','623001200010014433'),(2,'李艳','202110010102','123456',1,'2000-03-19',''),(3,'苗姗姗','202110010302','123456',0,'2001-10-12','314002200110125523'),(4,'李媛','202110010301','123456',0,'2002-11-22','314002200211225523');
/*!40000 ALTER TABLE `student` ENABLE KEYS */;
UNLOCK TABLES;

1.jdbcTemplate

不需要特殊的jar,只需配置即可
pom文件

<?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>

    <groupId>org.example</groupId>
    <artifactId>jdbc-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.17</version>
        </dependency>

    </dependencies>
</project>

配置多个数据源

server:
  port: 10010
spring:
  application:
    name: dynamic-datasource-jdbc
  datasource:
    master:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
      username: root
      password: root
    school:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
      username: root
      password: root

对数据源进行配置

package com.test.jdbc.config;

import com.zaxxer.hikari.HikariDataSource;
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.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-11-09 20:51
 */
@Configuration
public class DataSourceConfig {

    @Primary
    @Bean("master")
    @ConfigurationProperties("spring.datasource.master")
    public DataSource masterDataSource(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean("school")
    @ConfigurationProperties("spring.datasource.school")
    public DataSource schoolDataSource(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean("master")
    public JdbcTemplate masterTemplate(@Qualifier("master") DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }

    @Bean("schoolTemplate")
    public JdbcTemplate schoolTemplate(@Qualifier("school") DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }
}

启动类,因为用knife做测试,所以需要@EnableOpenApi

package com.test.jdbc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.oas.annotations.EnableOpenApi;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-11-11 20:33
 */
@SpringBootApplication
@EnableOpenApi
public class JdbcService {
    public static void main(String[] args) {
        SpringApplication.run(JdbcService.class,args);
    }
}

分别写实体,接口及实现类进行测试
实体类

package com.test.jdbc.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;

import java.io.Serializable;
import java.sql.Date;

/**
 * 学生表
 * @TableName student
 */
@Data
public class Student implements Serializable {
    /**
     * id
     */
    @TableId(type = IdType.AUTO)
    private Integer id;

    /**
     * 学生姓名
     */
    private String studentName;

    /**
     * 学号
     */
    private String studentNo;

    /**
     * 密码
     */
    private String password;

    /**
     * 性别:0-男,1-女
     */
    private Boolean sex;

    /**
     * 生日
     */
    private Date birthday;//java.sql.Date对应数据库date类型,只显示年月日

    /**
     * 身份证号
     */
    private String cardId;

    /**
     * 手机号
     */
    @TableField(exist = false)
    @JsonIgnore
    private String phone;

}


package com.test.jdbc.domain;

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

import java.io.Serializable;
import java.sql.Date;

/**
 * 用户表
 * @TableName user
 */
@Data
public class User implements Serializable {
    /**
     * id
     */
    @TableId(type = IdType.AUTO)
    private Integer id;

    /**
     * 用户名
     */
    private String username;

    /**
     * 真实姓名
     */
    private String realName;

    /**
     * 密码
     */
    private String password;

    /**
     * 性别:0-男,1-女
     */
    private Boolean sex;

    /**
     * 生日
     */
    private Date birthday;//java.sql.Date对应数据库date类型,只显示年月日

    /**
     * 身份证号
     */
    private String cardId;

    /**
     * 手机号
     */
    private String phone;

    private static final long serialVersionUID = 1L;
}

接口

package com.test.jdbc.controller;

import com.test.jdbc.domain.Student;
import com.test.jdbc.domain.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-11-11 20:31
 */
@RestController
public class TestController {

    @Autowired
    private JdbcTemplate masterTemplate;

    @Autowired
    private JdbcTemplate schoolTemplate;


    @GetMapping("getUserList")
    public List<User> getUserList(){
        List<User> list = masterTemplate.query("select * from user", new BeanPropertyRowMapper<>(User.class));
        return list;
    }

    @GetMapping("getStudentList")
    public List<Student> getStudentList(){
        List<Student> students = schoolTemplate.query("select * from student", new BeanPropertyRowMapper<>(Student.class));
        return students;
    }

    @GetMapping("getStudent")
    public List<Student> getStudent(){
        String sql = "select * from student";
        List<Student> list = schoolTemplate.query(sql, new BeanPropertyRowMapper<>(Student.class));
        list.stream().forEach(student -> {
            if (StringUtils.isNotBlank(student.getCardId())){
                String phone = masterTemplate.queryForObject("select phone from user where card_id = ?",String.class);
                student.setPhone(phone);
            }
        });
        return list;
    }
}

浏览器输入http://localhost:10010/doc.html
在这里插入图片描述
在这里插入图片描述

2.使用切面

需要额外写注解
pom

<?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>

    <groupId>org.example</groupId>
    <artifactId>aop-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.17</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
    </dependencies>
</project>

配置文件

server:
  port: 10011
spring:
  application:
    name: dynamic-datasource-aop
  datasource:
    master:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
      username: root
      password: root
    school:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
      username: root
      password: root

启动类

package com.test.aop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import springfox.documentation.oas.annotations.EnableOpenApi;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-11-09 20:37
 */
@EnableOpenApi
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//排除数据源自动注入,不然会报错
public class AopSourceService {
    public static void main(String[] args) {
        SpringApplication.run(AopSourceService.class,args);
    }
}

自定义注解

package com.test.aop.annonation;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSourceSwitch {

    public String dataSourceName() default "";
}

自定义注解的切面实现

package com.test.aop.aop;

import com.test.aop.annonation.DataSourceSwitch;
import com.test.aop.config.DynamicDataSourceHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class DataSourceAspect {

    @Pointcut("@annotation(com.test.aop.annonation.DataSourceSwitch)")
    public void pointCut(){
    }

    @Before("pointCut()")
    public void before(JoinPoint joinpoint){
        MethodSignature signature = (MethodSignature)joinpoint.getSignature();
        Method method = signature.getMethod();
        DataSourceSwitch annotation = method.getAnnotation(DataSourceSwitch.class);
        DynamicDataSourceHolder.setDatasourcePool(annotation.dataSourceName());
    }

    @After("pointCut()")
    public void after(){
        DynamicDataSourceHolder.removeDatasourcePool();
    }
}

数据源配置类

package com.test.aop.config;

import com.test.aop.enums.DataSourceType;
import com.zaxxer.hikari.HikariDataSource;
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 javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-11-09 20:51
 */
@Configuration
public class DataSourceConfig {

    @Bean("masterDataSource")
    @ConfigurationProperties("spring.datasource.master")
    public DataSource masterDataSource(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean("schoolDataSource")
    @ConfigurationProperties("spring.datasource.school")
    public DataSource schoolDataSource(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Primary
    @Bean("dynamicDataSource")
    public DynamicDataSource dynamicDataSource(){
        Map<Object,Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.TEST.name(),masterDataSource());
        targetDataSources.put(DataSourceType.SCHOOL.name(),schoolDataSource());
        return new DynamicDataSource(masterDataSource(),targetDataSources);
    }

    /*@Bean("masterTemplate")
    public JdbcTemplate masterTemplate(@Qualifier("masterDataSource") DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }

    @Bean("schoolTemplate")
    public JdbcTemplate schoolTemplate(@Qualifier("schoolDataSource") DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }*/
}


package com.test.aop.config;

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

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

public class DynamicDataSource extends AbstractRoutingDataSource {

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object,Object> targetDataSource){
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSource);
        super.afterPropertiesSet();
    }
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceHolder.getDatasourcePool();
    }
}


package com.test.aop.config;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-11-09 20:54
 */
public class DynamicDataSourceHolder {

    public static ThreadLocal<String> DATASOURCE_POOL = new ThreadLocal<>();

    /**
     * 获取数据源变量
     * @return
     */
    public static String getDatasourcePool(){
        return DATASOURCE_POOL.get();
    }

    /**
     * 设置数据源变量
     * @param name
     */
    public static void setDatasourcePool(String name){
        DATASOURCE_POOL.set(name);
    }

    public static void removeDatasourcePool(){
        DATASOURCE_POOL.remove();
    }
}

数据源类型枚举

package com.test.aop.enums;

public enum DataSourceType {
    TEST,
    SCHOOL,
    ;
}

接口或实现类使用注解

package com.test.aop.controller;

import com.test.aop.annonation.DataSourceSwitch;
import com.test.aop.domain.Student;
import com.test.aop.domain.User;
import com.test.aop.service.StudentService;
import com.test.aop.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-11-09 20:58
 */

@RestController
public class TestController {

    @Autowired
    private UserService userService;

    @Autowired
    private StudentService studentService;

    @GetMapping("user/list")
    public List<User> userList(){
        return userService.list();
    }

    @GetMapping("student/list")
    @DataSourceSwitch(dataSourceName = "SCHOOL")
    public List<Student> studentList(){
        return studentService.list();
    }

    @PostMapping("user/save")
    public void saveUser(@RequestBody User user){
        userService.save(user);
    }

    @PostMapping("student/save")
    @DataSourceSwitch(dataSourceName = "SCHOOL")
    public void saveStudent(@RequestBody Student student){
        studentService.save(student);
    }

    @GetMapping("registerToUser")
    public void registerToUser(Integer id,String username,String phone,String cardId){
        userService.registerTiUser(id,username,phone,cardId);
    }

    /**
     *
     * @return
     */
    @GetMapping("list")
    public List<Student> list(){
        return studentService.getPhone();
    }
}

3.mybatis层次的多数据源

需要每个库写一个配置类
pom

server:
  port: 10012
spring:
  application:
    name: dynamic-datasource-mybatis
  datasource:
    master:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
      username: root
      password: root
    school:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
      username: root
      password: root

启动类

package com.test.mybatis;

import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
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 springfox.documentation.oas.annotations.EnableOpenApi;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-11-11 21:06
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, MybatisPlusAutoConfiguration.class})
@EnableOpenApi
public class MybatisService {
    public static void main(String[] args) {
        SpringApplication.run(MybatisService.class,args);
    }
}

数据源配置文件

package com.test.mybatis.config;

import com.sun.tracing.ProbeName;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
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.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-11-11 21:14
 */
@Configuration
@MapperScan(basePackages = "com.test.mybatis.mapper.test",sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.master")
    public DataSource masterDatasource(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Primary
    @Bean
    public SqlSessionFactory masterSqlSessionFactory()throws Exception{
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(masterDatasource());
        return bean.getObject();
    }

    @Primary
    @Bean
    public DataSourceTransactionManager masterTransactionManager(){
        DataSourceTransactionManager manager = new DataSourceTransactionManager();
        manager.setDataSource(masterDatasource());
        return manager;
    }

    @Bean
    public TransactionTemplate masterTemplate(){
        return new TransactionTemplate(masterTransactionManager());
    }

}

package com.test.mybatis.config;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
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.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;

/**
 * @author清梦
 * @site www.xiaomage.com
 * @company xxx公司
 * @create 2023-11-11 21:14
 */
@Configuration
@MapperScan(basePackages = "com.test.mybatis.mapper.school",sqlSessionFactoryRef = "schoolSqlSessionFactory")
public class SchoolDataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.school")
    public DataSource schoolDatasource(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean
    public SqlSessionFactory schoolSqlSessionFactory()throws Exception{
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(schoolDatasource());
        return bean.getObject();
    }

    @Bean
    public DataSourceTransactionManager schoolTransactionManager(){
        DataSourceTransactionManager manager = new DataSourceTransactionManager();
        manager.setDataSource(schoolDatasource());
        return manager;
    }

    @Bean
    public TransactionTemplate schoolTemplate(){
        return new TransactionTemplate(schoolTransactionManager());
    }

}


4.spring的dynamic自动注入

需要引入dynamic-datasource-spring-boot-starter,实现类使用注解@DS(“数据源”)即可
pom

<?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>

    <groupId>org.example</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

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

    </dependencies>
</project>

配置文件有点不同

server:
  port: 10013
spring:
  application:
    name: dynamic-datasource-spring
  datasource:
    dynamic:
      primary: master
      datasource:
        master:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
          username: root
          password: root
        school:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
          username: root
          password: root

启动类

@SpringBootApplication
@EnableOpenApi
public class SpringAutoService{

    public static void main(String[] args) {
        SpringApplication.run(SpringAutoService.class,args);
    }
}

在实现类使用注解

package com.test.spring.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.test.spring.domain.Student;
import com.test.spring.mapper.StudentMapper;
import com.test.spring.mapper.UserMapper;
import com.test.spring.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
*
*/
@Service
@DS("school")
public class StudentServiceImpl extends ServiceImpl<StudentMapper,Student> implements StudentService{


    @Autowired
    private UserMapper userMapper;

    @Override
    public List<Student> getPhone() {
        List<Student> list = list();
        list.stream().filter(student -> StringUtils.isNotBlank(student.getCardId())).forEach(student -> {
            String phone = userMapper.selectPhoneByCardId(student.getCardId());
            student.setPhone(phone);
        });
        return list;
    }

}

package com.test.spring.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.test.spring.domain.Student;
import com.test.spring.domain.User;
import com.test.spring.mapper.StudentMapper;
import com.test.spring.mapper.UserMapper;
import com.test.spring.service.StudentService;
import com.test.spring.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


/**
*
*/
@Service
@DS("master")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Override
    public void registerTiUser(Integer id, String username, String phone, String cardId) {
        Student student = studentMapper.selectById(id);
        if (null == student){
            throw new RuntimeException("该学生不存在");
        }
        User user = new User();
        user.setRealName(student.getStudentName());
        BeanUtils.copyProperties(student,user);
        user.setUsername(username);
        user.setPhone(phone);
        user.setCardId(cardId);
        userMapper.insert(user);
    }

}

源码地址:https://gitee.com/qfp17393120407/dynamic-datasource-new.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/138785.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Debug】此语法需要一个导入的帮助程序,但找不到模块“tslib”

报错如下&#xff1a; 代码可以编译运行&#xff0c;但是会有红线和报错。 解决方法&#xff1a;TypeScript error “TS2354: This syntax requires an imported helper but module ‘tslib’ cannot be found” Issue #37991 microsoft/TypeScript GitHub 在tsconfig.jso…

MacOS下VMware Fusion配置静态IP

前言 在虚拟机安装系统后&#xff0c;默认是通过DHCP动态分配的IP&#xff0c;这会导致每次重启虚拟机ip都可能会改变&#xff0c;使用起来会有很多不便。 配置静态IP 查看主机网关地址 cat /Library/Preferences/VMware\ Fusion/vmnet8/nat.conf 查看主机DNS&#xff0c;m…

3种方法,教你用Pytest更改自动化测试用例执行顺序!

前言 在自动化测试中&#xff0c;自动化测试用例设计原则就是&#xff1a;执行过程时不能存在依赖顺序。那么如果测试用例需要按照指定顺序执行&#xff0c;这个时候应该怎么做呢&#xff1f; 目前单元测试框架中UnitTest没有办法改变测试用例的执行顺序&#xff0c;但是另一…

数据结构-数型查找

二叉排序树&#xff08;BST&#xff09; 二叉排序树&#xff0c;又称二叉查找树&#xff08;BST&#xff0c;Binary Search Tree&#xff09; 一颗二叉树或者是空二叉树&#xff0c;或者是具有如下性质的二叉树&#xff1a; 左子树上所有结点的关键字均小于根结点的关键字&…

微信支付配置完整操作手册

微信支付配置 必须申请开通微信支付 微信支付官方地址&#xff1a;https://pay.weixin.qq.com/index.php/core/home/login?return_url%2F 申请指引&#xff1a;https://pay.weixin.qq.com/index.php/public/bare_applyment/login4bank 百度经验&#xff1a;https://jingyan.b…

什么是智能井盖?万宾科技的智能井盖传感器的效果

近年来为打造智慧城市政府一直在不懈努力。加速城市基础建设是一项重要的举措&#xff0c;它有助于推动城市综合治理城市生命线的建设工程。在改善市民生活质量的过程中&#xff0c;市政部门正积极进行井盖的改进和升级工作&#xff0c;特别是那些看似微不足道的井盖却蕴含着重…

实时数仓-Flink使用总结

阿里云实时计算Flink版是阿里云基于Apache Flink构建的企业级、高性能实时大数据处理系统。具备一站式开发运维管理平台&#xff0c;支持作业开发、数据调试、运行与监控、自动调优、智能诊断等全生命周期能力。本期将对Flink的使用进行总结。 1. Flink产品回顾 阿里云实时计算…

第八章 :如何基于Spring Boot +Mybatis 快速开发 Restful API

第八章 :如何基于Spring Boot +Mybatis 快速开发 Restful API 前言 本章知识重点:主要讲解开发人员如何利用【MybatisPlus+EasyCode插件 】快速开发Restful API ,利用节约的时间学习,养成一种正向循环的技术之道,最后达到终身学习成长! 案例基于SpringBoot 2.3.2.RELEASE…

北斗卫星为油气管道安全保障提供可靠技术支持

北斗卫星为油气管道安全保障提供可靠技术支持 随着现代社会对能源需求的不断增长&#xff0c;油气管道成为了能源输送的重要通道。然而&#xff0c;油气管道的安全风险也日益凸显。为了及时掌握油气管道的运行状态并有效地监测其安全状况&#xff0c;北斗卫星技术为油气管道监测…

企业真正的性能测试,压测-内存泄露案例分析,一篇概全...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、环境配置 1&a…

OCR转换技巧:如何避免图片转Word时出现多余的换行?

在将图片中的文字识别转换为Word文档时&#xff0c;我们很多时候时会遇到识别内容的一个自然段还没结束就换行的问题&#xff0c;这些就是我们常说的多余换行的问题。为什么会产生这个问题呢&#xff1f;主要是由于OCR返回的识别结果是按图片上的文字换行而换行&#xff0c;而不…

VM虚拟机只有一个C盘怎么添加硬盘新分区盘符

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 前言 VM虚拟机中安装Window 系统后&#x…

Docker学习——⑦

文章目录 1、Docker 为什么需要网络管理2、Docker 网络架构简介2.1 CNM2.2 Libnetwork2.3 驱动 3、常见网络类型4、docker 网络管理命令5、网络详解5.2 docker Bridge 网络5.2 docker Host 网络5.3 docker Container 网络5.4 docker none 网络 1、Docker 为什么需要网络管理 容…

北京永达理慈善基金会与望京街道携手,为乡村振兴贡献10万元

东西部协作是推进巩固脱贫攻坚成果同乡村振兴有效衔接的重要手段。北京市朝阳区人民政府望京街道办事处自2021年起与内蒙古自治区通辽市科左后旗散都苏木、查日苏镇开展为期五年的结对帮扶工作&#xff0c;并号召全社会各界企事业单位及爱心人士帮扶助力&#xff0c;奉献爱心。…

新加坡建筑设备公司【Ten-League】申请3230万美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;总部位于新加坡的重型建筑设备和工程咨询服务公司Ten-League International Holdings Limited&#xff08;简称&#xff1a;Ten-League&#xff09;近期已向美国证券交易委员会&#xff08;SEC&am…

java--String使用时的注意事项

1.String使用时的注意事项 第一点&#xff1a; ①String对象的内容不可改变&#xff0c;被称为不可变字符串对象。(因为字符串是引用类型&#xff0c;每次都是引用一个地址&#xff0c;就相当于你有车&#xff0c;但是你不可能天天把车踹兜里&#xff0c;只能把钥匙踹兜里&am…

【2021集创赛】Risc-v杯三等奖:基于E203 ShuffleNet的图像识别SoC

本作品参与极术社区组织的有奖征集|秀出你的集创赛作品风采,免费电子产品等你拿~活动。 团队介绍 参赛单位&#xff1a;中国科学技术大学 队伍名称&#xff1a;Supernova 总决赛奖项&#xff1a;三等奖 1.项目简介 本设计以E203处理器为核心&#xff0c;添加协处理器、神经网…

孙哥Spring源码第29集

第29集 解析事务属性中的传播属性 【视频来源于&#xff1a;B站up主孙帅suns Spring源码视频】【微信号&#xff1a;suns45】 1、事务属性有哪些&#xff1f; 1、事务属性2、传播属性3、只读属性 设置事务为只读&#xff0c;提高事务运行的效率 false 4、超时属性 超时属性 通…

HarmonyOS 学习记录

时光荏苒,岁月如梭,韶华不负,未来可期。转眼间已经30岁了&#xff0c;学习的重要性不言而喻&#xff0c;在接下来的日子里记录下自己学习HarmonyOS的过程。增加一下知识储备&#xff0c;防患于未然嘛 不得不说华为的开发文档写的不错&#xff0c;开发工具直接安装后自动配置环境…

广告业展示服务预约小程序的效果如何

虽然不少人不会与广告业直接接触&#xff0c;但各种形式的广告却是充斥在人们生活中&#xff0c;线下的传单展板、线上的视频、音频、图文等都是广告很好的传播通道&#xff0c;同时广告业能扩展的客户属性也非常广&#xff0c;下到超市小摊&#xff0c;上到企业公司都有大小相…