当前位置: 代码网 > it编程>编程语言>Java > Spring Boot 3.4.0 结合 Mybatis-plus 实现动态数据源的完整方案

Spring Boot 3.4.0 结合 Mybatis-plus 实现动态数据源的完整方案

2025年04月01日 Java 我要评论
前言在实际企业级应用开发中,多数据源的需求非常常见。本文将详细介绍如何在 spring boot 3.4.0 项目中结合 mybatis-plus 实现动态数据源切换功能。一、环境准备首先确保你的开发

前言

在实际企业级应用开发中,多数据源的需求非常常见。本文将详细介绍如何在 spring boot 3.4.0 项目中结合 mybatis-plus 实现动态数据源切换功能。

一、环境准备

首先确保你的开发环境满足以下要求:

  • jdk 17+
  • spring boot 3.4.0
  • mybatis-plus 3.5.3.1+
  • maven 3.6.3+

二、项目配置

1. 添加依赖

pom.xml 中添加以下依赖:

<dependencies>
    <!-- spring boot starter -->
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-web</artifactid>
    </dependency>
    <!-- mybatis-plus -->
    <dependency>
        <groupid>com.baomidou</groupid>
        <artifactid>mybatis-plus-boot-starter</artifactid>
        <version>3.5.3.1</version>
    </dependency>
    <!-- 数据库驱动 -->
    <dependency>
        <groupid>mysql</groupid>
        <artifactid>mysql-connector-java</artifactid>
        <scope>runtime</scope>
    </dependency>
    <!-- 其他工具 -->
    <dependency>
        <groupid>org.projectlombok</groupid>
        <artifactid>lombok</artifactid>
        <optional>true</optional>
    </dependency>
</dependencies>

2. 配置文件

application.yml 中配置多个数据源:

spring:
  datasource:
    master:
      driver-class-name: com.mysql.cj.jdbc.driver
      url: jdbc:mysql://localhost:3306/master_db?usessl=false&servertimezone=utc
      username: root
      password: 123456
    slave1:
      driver-class-name: com.mysql.cj.jdbc.driver
      url: jdbc:mysql://localhost:3306/slave1_db?usessl=false&servertimezone=utc
      username: root
      password: 123456
    slave2:
      driver-class-name: com.mysql.cj.jdbc.driver
      url: jdbc:mysql://localhost:3306/slave2_db?usessl=false&servertimezone=utc
      username: root
      password: 123456

三、实现动态数据源

1. 数据源枚举

public enum datasourcetype {
    master("master"),
    slave1("slave1"),
    slave2("slave2");
    private final string name;
    datasourcetype(string name) {
        this.name = name;
    }
    public string getname() {
        return name;
    }
}

2. 动态数据源上下文

public class dynamicdatasourcecontextholder {
    private static final threadlocal<string> context_holder = new threadlocal<>();
    public static void setdatasourcetype(string datasourcetype) {
        context_holder.set(datasourcetype);
    }
    public static string getdatasourcetype() {
        return context_holder.get();
    }
    public static void cleardatasourcetype() {
        context_holder.remove();
    }
}

3. 动态数据源配置

@configuration
@mapperscan(basepackages = "com.example.mapper")
public class dynamicdatasourceconfig {
    @bean
    @configurationproperties("spring.datasource.master")
    public datasource masterdatasource() {
        return datasourcebuilder.create().build();
    }
    @bean
    @configurationproperties("spring.datasource.slave1")
    public datasource slave1datasource() {
        return datasourcebuilder.create().build();
    }
    @bean
    @configurationproperties("spring.datasource.slave2")
    public datasource slave2datasource() {
        return datasourcebuilder.create().build();
    }
    @bean
    public datasource dynamicdatasource() {
        map<object, object> targetdatasources = new hashmap<>();
        targetdatasources.put(datasourcetype.master.getname(), masterdatasource());
        targetdatasources.put(datasourcetype.slave1.getname(), slave1datasource());
        targetdatasources.put(datasourcetype.slave2.getname(), slave2datasource());
        dynamicdatasource dynamicdatasource = new dynamicdatasource();
        dynamicdatasource.settargetdatasources(targetdatasources);
        dynamicdatasource.setdefaulttargetdatasource(masterdatasource());
        return dynamicdatasource;
    }
    @bean
    public platformtransactionmanager transactionmanager(datasource datasource) {
        return new datasourcetransactionmanager(datasource);
    }
}

4. 动态数据源实现

public class dynamicdatasource extends abstractroutingdatasource {
    @override
    protected object determinecurrentlookupkey() {
        return dynamicdatasourcecontextholder.getdatasourcetype();
    }
}

5. 自定义注解

@target({elementtype.method, elementtype.type})
@retention(retentionpolicy.runtime)
@documented
public @interface datasource {
    datasourcetype value() default datasourcetype.master;
}

6. aop 切面实现

@aspect
@component
@order(-1)
@slf4j
public class datasourceaspect {
    @pointcut("@annotation(com.example.annotation.datasource)" +
            "|| @within(com.example.annotation.datasource)")
    public void dspointcut() {
    }
    @around("dspointcut()")
    public object around(proceedingjoinpoint point) throws throwable {
        datasource datasource = getdatasource(point);
        if (datasource != null) {
            dynamicdatasourcecontextholder.setdatasourcetype(datasource.value().getname());
        }
        try {
            return point.proceed();
        } finally {
            dynamicdatasourcecontextholder.cleardatasourcetype();
        }
    }
    private datasource getdatasource(proceedingjoinpoint point) {
        methodsignature signature = (methodsignature) point.getsignature();
        datasource datasource = annotationutils.findannotation(signature.getmethod(), datasource.class);
        if (datasource != null) {
            return datasource;
        }
        return annotationutils.findannotation(signature.getdeclaringtype(), datasource.class);
    }
}

四、使用示例

1. service 层使用

@service
public class userserviceimpl implements userservice {
    @autowired
    private usermapper usermapper;
    @override
    @datasource(datasourcetype.master)
    public user getmasteruser(long id) {
        return usermapper.selectbyid(id);
    }
    @override
    @datasource(datasourcetype.slave1)
    public user getslave1user(long id) {
        return usermapper.selectbyid(id);
    }
    @override
    @datasource(datasourcetype.slave2)
    public user getslave2user(long id) {
        return usermapper.selectbyid(id);
    }
}

2. controller 层调用

@restcontroller
@requestmapping("/user")
public class usercontroller {
    @autowired
    private userservice userservice;
    @getmapping("/master/{id}")
    public user master(@pathvariable long id) {
        return userservice.getmasteruser(id);
    }
    @getmapping("/slave1/{id}")
    public user slave1(@pathvariable long id) {
        return userservice.getslave1user(id);
    }
    @getmapping("/slave2/{id}")
    public user slave2(@pathvariable long id) {
        return userservice.getslave2user(id);
    }
}

五、注意事项

  • 事务管理:动态数据源切换与事务管理需要特别注意,建议在事务方法中不要切换数据源
  • 连接池配置:可以为每个数据源单独配置连接池参数
  • 性能考虑:频繁切换数据源可能会影响性能,应根据实际需求合理设计
  • 异常处理:做好数据源切换失败时的异常处理

六、总结

本文详细介绍了在 spring boot 3.4.0 项目中结合 mybatis-plus 实现动态数据源切换的完整方案。通过自定义注解和aop切面,我们可以优雅地实现方法级别的数据源切换,满足多数据源场景下的各种需求。

到此这篇关于spring boot 3.4.0 结合 mybatis-plus 实现动态数据源的完整方案的文章就介绍到这了,更多相关spring boot mybatis-plus动态数据源内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com