baomidou dynamic-datasource 强制查询sql走主库

场景

因为引用了baomidou主从数据源,因为业务场景特殊,需要查询语句强制走主库,把解决方案分享出来,帮助大家少走弯路

pom依赖

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

主从配置

package com.baomidou.config;


import com.baomidou.dynamic.datasource.plugin.MasterSlaveAutoRoutingPlugin;
import com.baomidou.interceptor.MasterSlaveAutoRoutingOrSelectByRulePlugin;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * 主从配置
 */
@Configuration
public class MasterSlaveAutoRoutingPluginConfig {


    /**
     * xml文件sql语句标签名包含'FromMaster' 会去主库查询
     */

    @Bean
    public MasterSlaveAutoRoutingOrSelectByRulePlugin masterSlaveAutoRoutingPlugin(){
        return new MasterSlaveAutoRoutingOrSelectByRulePlugin();
    }

}

拦截器

package com.baomidou.interceptor;

import com.baomidou.dynamic.datasource.support.DdConstants;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Properties;

/**
 * 根据 baomidou MasterSlaveAutoRoutingPlugin 修改符合自己的调用规则(目前根据sql方法的唯一id来判断)
 * 自动切换主从或者根据方法名指定路由
 */
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@Slf4j
public class MasterSlaveAutoRoutingOrSelectByRulePlugin implements Interceptor {
    /**
     * xml文件sql语句标签名包含'FromMaster' 会去主库查询
     * 如 '<select id="find***FromMaster" ...>'
     */
    public static final String FROM_MASTER = "FromMaster";


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        String pushedDataSource = null;
        try {
            if (ms.getId().contains(MasterSlaveAutoRoutingOrSelectByRulePlugin.FROM_MASTER_HT) && SqlCommandType.SELECT == ms.getSqlCommandType()) {
                pushedDataSource = DynamicDataSourceContextHolder.push(DdConstants.MASTER);
                return invocation.proceed();
            }

            String dataSource = SqlCommandType.SELECT == ms.getSqlCommandType() ? DdConstants.SLAVE : DdConstants.MASTER;
            pushedDataSource = DynamicDataSourceContextHolder.push(dataSource);
            return invocation.proceed();
        } finally {
            if (pushedDataSource != null) {
                DynamicDataSourceContextHolder.poll();
            }
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }
}

dao

package com.baomidou.mapper;

import com.baomidou.entity.TOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * <p>
 * Mapper 接口
 * </p>

 */
public interface TOrderMapper extends BaseMapper<TOrder> {

    TOrder findOrderFromMaster();

}

xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.baomidou.mapper.TOrderMapper">

    
    <select id="findOrderFromMaster" resultType="com.baomidou.entity.TOrder">
            --    根据名称使sql强制走主库
    </select>

</mapper>

Yml

server:
  port: 9914
  servlet:
    context-path: /baomidou
logging:
  level:
    com.baomidou.dynamic: debug
spring:
  datasource:
    dynamic:
      primary: master  # 这里需要修改
      strict: true
      hikari:
        pool-name: Yi_HikariCP
        minimum-idle: 5
        maximum-pool-size: 20
      datasource:
        # 测试
        master:
          type: com.zaxxer.hikari.HikariDataSource
          url: jdbc:mysql://localhost:3396/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
          username: admin
          password: ufcz2b8x3bas4c5m$%332
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave_1:
          type: com.zaxxer.hikari.HikariDataSource
          url: jdbc:mysql://localhost:3397/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
          username: readonly
          password: 123qwe!@#
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave_2:
          type: com.zaxxer.hikari.HikariDataSource
          url: jdbc:mysql://localhost:3397/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
          username: readonly
          password: 123qwe!@#
          driver-class-name: com.mysql.cj.jdbc.Driver
      #seata事务生效
      seata: true
      seata-mode: at

seata:
  enabled: true
  application-id: baomidou-seata
  #不使用自动代理数据源
  enable-auto-data-source-proxy: false
mybatis-plus:
#================================================= mybatis-plus start =================================================
  # classpath:/mapper/*Mapper.xml
  mapper-locations: classpath*:/mapper/*.xml
  # 实体扫描,多个package用逗号或者分号分隔
  type-aliases-package: com.user.entity
  configuration:
    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 驼峰下划线转换
    map-underscore-to-camel-case: true
    cache-enabled: false
    # 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
    call-setters-on-nulls: false
  global-config:
    # 刷新mapper 调试神器
    refresh: true
    banner: false
    #数据库大写下划线转换
    #capital-mode: true
    #序列接口实现类配置
    #key-generator: com.baomidou.springboot.xxx
    # 数据库相关配置
    db-config:
      db-type: mysql
      # 主键类型  AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
      id-type: UUID
      # 字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"
      field-strategy: NOT_EMPTY
      capital-mode: true
      #逻辑删除配置
      logic-delete-value: 1
      logic-not-delete-value: 0
#================================================= mybatis-plus end ===================================================

完结撒花 ✿✿ヽ(°▽°)ノ✿

当你遇到“Cannot resolve com.baomidou:dynamic-datasource-spring-boot-starter:3.5.0”的错误信息,通常意味着在你的项目中无法找到指定版本的`com.baomidou:dynamic-datasource-spring-boot-starter`依赖项。这可能是由于以下几个原因造成的: ### 解决步骤: 1. **确认依赖是否正确引入**: - 检查你的 `pom.xml` 文件或其他构建工具文件(如 Gradle 的 build.gradle),确保已经正确添加了所需的依赖。检查依赖的坐标、版本等信息是否完全匹配。 ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.5.0</version> </dependency> ``` 2. **更新Maven仓库配置**: 如果你的项目使用的是Maven作为构建工具,确保本地的Maven库已经包含了所需依赖。有时候,本地库可能过期或缺失。可以尝试清理并重新生成Maven项目,命令如下: ```bash mvn clean install ``` 3. **检查远程仓库状态**: 确认远程仓库(如中央仓库、阿里云maven仓库等)中包含所需的依赖版本。有时因为仓库维护或网络问题导致访问失败。 4. **更新到最新版本**: 若发现特定版本不可用,考虑将依赖升级到最新版本。这有可能解决兼容性和功能问题。 5. **使用第三方仓库**: 如果官方仓库无法获取到所需依赖,可以考虑从其他可信的第三方仓库(如JitPack或私有Maven仓库)下载。 6. **排除冲突**: 确保项目中没有依赖冲突。特别是如果你使用了其他的 Spring Boot 或 JDBC 数据源相关的组件,可能会存在版本或配置冲突。 7. **检查构建脚本语法**: 保证构建脚本中引用依赖的方式正确无误,尤其是路径分隔符和依赖属性的书写方式(例如使用 `/` 而不是 `\`)。 8. **查阅官方文档**: 查阅项目的官方文档或社区论坛,看是否有其他人遇到类似的问题及其解决方案。 9. **重新启动服务器**: 有时候,只是简单地重启应用服务器(如果是运行在本地环境的话)也可能解决问题。 如果以上步骤都试过了还是无法解决,建议提供更详细的日志信息和项目结构描述,以便更精确地定位问题所在。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值