多数据源切换

news2024/11/18 23:22:30

多数据源切换

  • 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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pandas笔记:读写excel

1 读excel read_excel函数能够读取的格式包含&#xff1a;xls, xlsx, xlsm, xlsb, odf, ods 和 odt 文件扩展名。 支持读取单一sheet或几个sheet。 1.0 使用的数据 1.1 主要使用方法 pandas.read_excel(io, sheet_name0, header0, namesNone, index_colNone, usecolsNon…

Nginx:如何实现一个域名访问多个项目

1. 背景介绍 最近在多个项目部署中遇到这样一个问题&#xff0c;一个域名如何实现多个项目的访问。因为不想自己单独去申请域名证书和域名配置&#xff0c;便想到了这个方案&#xff0c;结合Nginx的location功能实现了自己的需求&#xff0c;便记录下来。示例中是以项目演示&a…

基于Springboot菜谱美食饮食健康管理系统设计与实现

博主介绍&#xff1a;✌Csdn特邀作者、博客专家、博客云专家、B站程序阿龙带小白做毕设系列&#xff0c;项目讲解、B站粉丝排行榜前列、专注于Java技术领域和毕业项目实战✌ 有设计项目或者是研究参考的可以加微信&#xff1a;Script-Liu 或者是QQ:1339941174 使用的软件开发环…

KubeSphere 社区双周报 | KubeSphere 3.4.1 发布 | 2023.10.27-11.09

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者&#xff0c;并对近期重要的 PR 进行解析&#xff0c;同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为&#xff1a;2023.10.27-2023.…

游戏制作:猜数字(1~100),不会也可以先试着玩玩

目录 1 2代码如下&#xff1a;可以试着先玩玩 3运行结果&#xff1a;嘿嘿嘿 4程序分析&#xff1a;想学的看 5总结&#xff1a; 1 猜数范围为1~100&#xff0c;猜大输出猜大了&#xff0c;猜小输出猜小了&#xff0c;游戏可以无限玩。 首先先做一个简单的菜单界面&#xf…

Java入门篇 之 补 类与对象

本篇碎碎念&#xff1a;每个人的想法都不一样&#xff0c;不要强求&#xff0c;顺其自然&#xff0c;要相信&#xff0c;一切都在向好的方面前进&#xff01;&#xff01;&#xff01;&#xff01; 今日份励志文案:山海的浩瀚&#xff0c;宇宙的浪漫&#xff0c;都在我内心翻腾…

【Python】Matplotlib-多张图像的显示

一&#xff0c;情景描述 大家在写论文或者实验报告的时候&#xff0c;经常会放多张图片或数据图像在一起形成对比。比如&#xff0c;我现在有一张经过椒盐噪声处理的图像&#xff0c;现在进行三种滤波&#xff0c;分别是均值&#xff0c;高斯&#xff0c;中值滤波&#xff0c;…

计算机网络技术(一)

深入浅出计算机网络 微课视频_哔哩哔哩_bilibili 第一章概述 1.1 信息时代的计算机网络 1. 计算机网络各类应用 2. 计算机网络带来的负面问题 3. 我国互联网发展情况 1.2 因特网概述 1. 网络、互连网&#xff08;互联网&#xff09;与因特网的区别与关系 如图所示&#xff0…

计算机组成原理之处理器(流水线)

引言 为什么不采用单周期实现,硬件比较简单&#xff1f; 主要是因为效率太低&#xff0c;处理器中最长的路径&#xff08;一般是ld指令)决定了时钟周期 流水线概述 流水线是一种能使多条指令重叠执行的技术。 流水线更快的原因是所有的工作都在并行执行&#xff0c;所以单位…

Adversarial Training Methods for Deep Learning: A Systematic Review

Adversarial Training Methods for Deep Learning: A Systematic Review----《面向深度学习的对抗训练方法:系统回顾》 摘要 通过快速梯度符号法(FGSM)、投影梯度下降法(PGD)和其他攻击算法&#xff0c;深度神经网络暴露在对抗攻击的风险下。对抗性训练是用来防御对抗性攻击威…

【86 backtrader实现crypto交易策略】backtrader和ccxt对接实现中低频自动化交易-01

最近有点空闲,尝试把backtrader和一些实盘交易的接口对接一下,方便大家进行中低频交易,主要目标包括:股票(qmt),期货(ctpbee), crypto(ccxt),外盘交易(ib,已实现,但是版本比较旧,后期会继续更新). 这个周末尝试实现了backtrader和ccxt的对接,主要是参考了下面的开源代…

使用74HC165扩展uno的输入管脚

74HC165管脚定义&#xff1a; 使用3个管脚扩展接入个独立开关 const int dataPin 2; /* Q7 */ const int clockPin 3; /* CP */ const int latchPin 4; /* PL */ const int numBits 8; /* Set to 8 * number of shift registers */ void setup() { Serial.begin…

暴力递归转动态规划(十五)

题目 给定一个正数n&#xff0c;求n的裂开方法数&#xff0c; 规定&#xff1a;后面的数不能比前面的数小 比如4的裂开方法有&#xff1a; 1111、112、13、22、04 。 5种&#xff0c;所以返回5 暴力递归 用暴力递归方法进行尝试&#xff0c;整体思路是这样&#xff1a; 暴力递…

Java --- 直接内存

一、直接内存 1、不是虚拟机运行时数据区的一部分&#xff0c;也不是《Java虚拟机规范》中定义的内存区域。 2、直接内存是在Java堆外的&#xff0c;直接向系统申请的内存区间。 3、来源于NIO&#xff0c;通过存在堆中的DirectByteBuffer操作Native内存。 4、访问直接内存的…

Ubuntu 创建并发布 Django 项目

Ubuntu 创建并发布 Django 项目 升级操作系统和软件 sudo apt updatesudo apt -y dist-upgrade 安装 python3-pip sudo apt -y install python3-pip安装 django pip install -i https://pypi.tuna.tsinghua.edu.cn/simple djangosudo apt -y install python3-django创建 dj…

MongoDB基础知识~

引入MongoDB&#xff1a; 在面对高并发&#xff0c;高效率存储和访问&#xff0c;高扩展性和高可用性等的需求下&#xff0c;我们之前所学习过的关系型数据库(MySql,sql server…)显得有点力不从心&#xff0c;而这些需求在我们的生活中也是随处可见的&#xff0c;例如在社交中…

使用visualStudio发布可执行文件

编译成功后会在程序项目的路径下创建一个debug文件夹和一个release文件夹 文件夹中的具体文件入下所示 生成32位的可执行文件 32位的可执行文件可以在64位的计算机中执行&#xff0c;而64位的操作系统程序只能在64位的计算机中执行安装运行库的安装包根据电脑的版本选择合适的…

手机开机入网流程 KPI接通率和掉线率

今天我们来学习手机开机入网流程是怎么样的。以及RRC连接和重建流程(和博主之前讲TCP三次握手&#xff0c;四次挥手原理很相似)是什么样的&#xff0c;还有天线的KPI指标都包括什么&#xff0c;是不是很期待啊~ 目录 手机开机入网流程 ATTACH/RRC连接建立过程 KPI接通率和掉…

【YOLOv5】【模型压缩与加速】【量化】FP32、FP16、INT8

量化是将模型参数的存储类型从高精度存储降到低精度存储&#xff0c;从而达到减小模型体积大小、加快模型推理速度的效果。 目录 FP32量化 FP16量化 INT8量化 FP32量化 这个直接使用yolov5的export导出32位存储的 engine格式模型即可 python export.py --weights runs/train/…

前端---认识HTML

文章目录 什么是HTML&#xff1f;HTML的读取、运行HTML的标签注释标签标题标签段落标签换行标签格式化标签图片标签a标签表格标签列表标签表单标签form标签input标签文本框单选框复选框普通按钮提交按钮文件选择框 select标签textarea标签特殊标签div标签span标签 什么是HTML&a…