mybatis-plus3.5.x和3.4.x版本的代码生成工具

前言

这两天一直在弄我负责的那些项目开源组件升级,因为好多组件有漏洞,要升级版本。然后mybatis-plus也是其中之一,因为我一直用的版本是3.4.3,现在要升级到3.5.2版本以上。然后3.4.x和3.5.x有一些地方变动还是挺大的,主要就是在代码生成这一块,变动比较大,以前写得生成工具类已经不能用了。然后现在重新写了3.5.x版本的生成工具类。

这里我把3.4和3.5的都放上来,大家可以对比参考下。

3.4.x版本

<!-- mybatis_plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>
<!-- 代码生成器 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * 代码生成工具类
 */
public class GenerateUtil {
    /**
     * 数据库链接地址
     */
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false&serverTimezone=UTC";

    /**
     * 驱动
     */
    private static final String DRIVER_NAME = "com.mysql.cj.jdbc.Driver";

    /**
     * 用户名
     */
    private static final String USERNAME = "root";

    /**
     * 密码
     */
    private static final String PASSWORD = "123456";

    /**
     * 作者
     */
    private static final String AUTHOR = "fuHua";

    /**
     * 父包名
     */
    private static final String PACKAGE_PARENT = "com";

    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StrUtil.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }

    /**
     * 全局配置
     *
     * @return 返回 GlobalConfig
     */
    private static GlobalConfig getGlobalConfig() {
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor(AUTHOR);
        gc.setOpen(false);
        // 是否覆盖同名文件,默认是false
        gc.setFileOverride(true);
        // 不需要ActiveRecord特性的请改为false
        gc.setActiveRecord(false);
        // XML 二级缓存
        gc.setEnableCache(false);
        // XML ResultMap 生成基本的resultmap
        gc.setBaseResultMap(true);
        // XML columList 生成基本的sql片段
        gc.setBaseColumnList(false);
        //实体属性 Swagger2 注解
        //gc.setSwagger2(true);
        gc.setServiceName("");
        gc.setServiceImplName("%sService");
        return gc;
    }

    /**
     * 数据源配置
     *
     * @return 返回 getDataSourceConfig
     */
    private static DataSourceConfig getDataSourceConfig() {
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(URL);
        dsc.setDriverName(DRIVER_NAME);
        dsc.setUsername(USERNAME);
        dsc.setPassword(PASSWORD);
        return dsc;
    }

    /**
     * 包名配置
     *
     * @return 返回 PackageConfig
     */
    private static PackageConfig getPackageConfig() {
        PackageConfig pc = new PackageConfig();
        pc.setParent(PACKAGE_PARENT);
        //pc.setModuleName(scanner("模块名"));
        pc.setEntity("entity.sys");
        pc.setMapper("mapper.sys");
        pc.setService("");
        pc.setServiceImpl("service.sys");
        pc.setController("controller.sys");
        return pc;
    }

    /**
     * 模板引擎配置
     *
     * @return 返回 TemplateConfig
     */
    private static TemplateConfig getTemplateConfig() {
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setXml(null);
        return templateConfig;
    }

    /**
     * 策略配置
     *
     * @param tableNames 表名称
     *                   strategy.setInclude(tableNames) 传入需要 "生成" 的表名
     *                   strategy.setExclude(tableNames) 传入需要 "过滤" 的表名
     *                   strategy.setSuperEntityColumns("id");
     * @return 返回 getStrategyConfig
     */
    private static StrategyConfig getStrategyConfig(String... tableNames) {
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);

        // 公共父类
        strategy.setSuperEntityClass(PACKAGE_PARENT + ".common.base.BaseEntity");
        strategy.setSuperMapperClass(strategy.getSuperMapperClass());
        strategy.setSuperServiceImplClass(PACKAGE_PARENT + ".common.base.BaseService");
        strategy.setSuperControllerClass(PACKAGE_PARENT + ".common.base.BaseController");

        // 写于父类中的公共字段
        strategy.setSuperEntityColumns("id", "create_by", "create_time", "update_by", "update_time");

        strategy.setInclude(tableNames);
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix("_");
        strategy.setEntityTableFieldAnnotationEnable(true);
        strategy.setEntityLombokModel(true);
        return strategy;
    }

    /**
     * 自定义配置
     *
     * @return 返回 InjectionConfig
     */
    private static InjectionConfig getInjectionConfig() {
        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        // 如果模板引擎是 freemarker
        final String templatePath = "/templates/mapper.xml.ftl";
        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return System.getProperty("user.dir") + "/src/main/resources/mapper/sys/" + tableInfo.getEntityName() + "Mapper" + ".xml";
            }
        });
        cfg.setFileOutConfigList(focList);
        return cfg;
    }

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        mpg.setGlobalConfig(getGlobalConfig());
        // 数据源配置
        mpg.setDataSource(getDataSourceConfig());
        // 包配置
        mpg.setPackageInfo(getPackageConfig());
        // 自定义配置
        mpg.setCfg(getInjectionConfig());
        // 配置模板
        mpg.setTemplate(getTemplateConfig());
        // 策略配置
        //sys_dept,sys_dict,sys_log,sys_menu,sys_post,sys_role,sys_role_dept,sys_role_menu,sys_user,sys_user_post
        mpg.setStrategy(getStrategyConfig(scanner("表名,多个英文逗号分割").split(",")));
        // 设置模板引擎
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
}

3.5.x版本

<!-- mybatis_plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>
<!-- 代码生成器 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.3.1</version>
</dependency>
<!-- 代码生成器的模板引擎 -->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>

注意:一定要引入代码生成器的模板引擎,否则的话运行会报错:org/apache/velocity/context/Context

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.common.base.BaseController;
import com.common.base.BaseEntity;
import com.common.base.BaseService;

import java.util.Collections;
import java.util.List;

/**
 * 代码生成工具类
 */
public class CodeGenerator {

    /**
     * 数据库链接地址
     */
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false&serverTimezone=UTC";

    /**
     * 用户名
     */
    private static final String USERNAME = "root";

    /**
     * 密码
     */
    private static final String PASSWORD = "123456";

    /**
     * 作者
     */
    private static final String AUTHOR = "fuHua";

    /**
     * 表名的前缀,从表生成代码时会去掉前缀
     */
    private static final String TABLE_PREFIX = "";

    /**
     * 模块名
     */
    //private static final String MODULE_NAME = "";

    /**
     * 需要生成的表名,必填
     */
    private static final List<String> TABLES = ListUtil.toList("aqhdjl","aqyh","bqbhhjl","bwhyjl","chzttd","czpcx","dzhyj","gqjjc","gzpcx","qxdcx","whjx","yxfsd","zhtd");


    public static void main(String[] args) {
        if (CollUtil.isEmpty(TABLES)) {
            System.out.println("请输入需要生成的表名!");
            return;
        }

        String projectPath = System.getProperty("user.dir");

        //全局配置
        GlobalConfig config = new GlobalConfig.Builder()
                .author(AUTHOR)                                      //作者
                .outputDir(projectPath + "/src/main/java")          //生成文件输出路径(写到java目录)
                //.enableSwagger()                                  //开启swagger
                .commentDate("yyyy-MM-dd HH:mm:ss")                 //注释日期格式
                .dateType(DateType.TIME_PACK)                       //设置时间对应类型
                .disableOpenDir()                                   //生成后不要打开目录
                .build();

        //包名配置
        PackageConfig packageConfig = new PackageConfig.Builder()
                .parent("com")                      //父包名
                //.moduleName(moduleName)           //模块名
                .controller("controller.sys")       //controller包名
                //.service("service.sys")           //service接口包名
                .serviceImpl("service.sys")         //service实现类包名
                .entity("entity.sys")               //实体类包名
                .mapper("mapper.sys")               //mapper包名
                .xml("mapper.sys")                  //mapper对应的xml包名
                .pathInfo(Collections.singletonMap(OutputFile.mapper.xml, projectPath + "/src/main/resources/mapper/sys"))                  //mapper对应的xml路径
                .build();

        //策略配置
        StrategyConfig strategyConfig = new StrategyConfig.Builder()
                .addTablePrefix(TABLE_PREFIX)                       //需要抵消的表前缀
                .addInclude(TABLES)                                 //设置生成需要映射的表名
                //.enableCapitalMode()                              //策略开启⼤写命名

                .serviceBuilder()                                   //构建Service层
                .enableFileOverride()                               //覆盖文件(需谨慎使用)
                .formatServiceImplFileName("%sService")             //业务层接口实现类命名
                .superServiceImplClass(BaseService.class)           //service公共父类

                .entityBuilder()                                    //构建实体类
                .enableFileOverride()                               //覆盖文件(需谨慎使用)
                .superClass(BaseEntity.class)                       //entity公共父类
                .addSuperEntityColumns("id","updateTime","createTime") // 公共字段
                .columnNaming(NamingStrategy.underline_to_camel)    //字段名驼峰命名
                .naming(NamingStrategy.underline_to_camel)          //表名驼峰命名
                .enableLombok()                                     //添加lombock的getter、setter注解
                //.enableChainModel()                               //启动链式写法@Accessors(chain = true)
                //.enableColumnConstant()                           //启动属性转常量功能@FieldNameConstants
                //.logicDeleteColumnName("deleted")                 //逻辑删除字段,标记@TableLogic
                .enableTableFieldAnnotation()                       //启动字段注解
                //.addTableFills(tableFillList)                     //属性值填充策略

                .controllerBuilder()                                //构建Controller类
                .enableFileOverride()                               //覆盖文件(需谨慎使用)
                .enableHyphenStyle()                                //映射路径使用连字符格式,而不是驼峰
                .formatFileName("%sController")                     //Controller类命名
                .superClass(BaseController.class)                   //Controller 类继承 BaseController
                .enableRestStyle()                                  //标记@RestController注解

                .mapperBuilder()                                    //构建mapper接口类
                .enableFileOverride()                               //覆盖文件(需谨慎使用)
                .enableBaseResultMap()                              //生成基本的resultMap
                .formatMapperFileName("%sMapper")                   //Mapper接口类明名
                .superClass(BaseMapper.class)                       //Mapper接口类集成 BaseMapper
                //.enableMapperAnnotation()                         //标记@Mapper注解
                .formatXmlFileName("%sMapper")                      //Mapper.xml命名
                .enableBaseColumnList()                             //生成基本的SQL片段

                .build();

        //数据源配置
        DataSourceConfig.Builder dataSourceConfigBuilder = new DataSourceConfig.Builder(URL,USERNAME,PASSWORD);
        //数据库类型转换器
        dataSourceConfigBuilder.typeConvert(new MySqlTypeConvert() {
            /*@Override
            public IColumnType processTypeConvert(GlobalConfig globalConfig, String tableField) {
                if (tableField.toLowerCase().contains("date") || tableField.toLowerCase().contains("timestamp") || tableField.toLowerCase().contains("datetime")) {
                    return DbColumnType.STRING;
                }
                return super.processTypeConvert(globalConfig, tableField);
            }*/
        });

        //创建代码生成器对象,加载配置
        AutoGenerator autoGenerator = new AutoGenerator(dataSourceConfigBuilder.build());
        autoGenerator.global(config);
        autoGenerator.packageInfo(packageConfig);
        autoGenerator.strategy(strategyConfig);

        //执行
        autoGenerator.execute();
        System.out.println("========================================  相关代码生成完毕  =====================================");
    }
}

以上就是全部代码了,引入依赖后,代码可以直接复制使用,改一下数据库连接、用户名、密码,还有包名。

<think>好的,我现在需要帮助用户解决在Spring BootMyBatis项目中动态切换MyBatis-Plus的mapper-locations路径的问题,具体是在MySQL达梦数据库之间切换不同的映射文件。用户之前的问题回答已经涉及了动态重建SqlSessionFactory配置管理器的使用,现在需要结合用户提供的引用内容来优化解决方案。 首先,我需要理解用户的需求。用户希望在同一个应用中根据不同的数据库(如MySQL达梦)动态切换使用不同的XML映射文件。这可能是因为不同数据库的SQL语法或函数有所差异,需要不同的实现。用户已经提供了之前的回答,其中提到了动态重建SqlSessionFactory配置管理器的方法,现在需要结合引用中的信息来调整方案。 根据引用[1]到[5],用户提供的引用主要解释了mapper-locations的配置方式,特别是classpathclasspath*的区别,以及如何指定多个路径。例如,引用[4]指出classpath*会搜索所有类路径下的匹配资源,而classpath只找第一个。此外,引用[3]提到了使用@MapperScan来扫描不同的Mapper接口位置,这可能对动态切换有帮助。 接下来,我需要考虑如何动态切换mapper-locations。之前的回答中提到了通过重建SqlSessionFactory并刷新Mapper接口代理对象来实现。现在需要结合用户提供的不同路径(MySQL达梦的mapper文件路径),可能需要调整配置管理器,使其能够根据需求加载不同的路径。 用户的目标是根据需求切换两个不同的路径:classpath*:mapper/mysqlMapper/**/*Mapper.xml classpath*:mapper/damengmapper/**/*Mapper.xml。这意味着需要根据当前使用的数据库类型动态切换这两个路径。 我需要确保解决方案能够处理以下几点: 1. 动态修改MyBatis-Plus的mapper-locations配置。 2. 在切换配置后,重新加载对应的XML映射文件。 3. 保证线程安全事务一致性,尤其是在生产环境中。 4. 可能需要处理多数据源的情况,但用户的问题更侧重于同一数据源下不同mapper文件的切换。 考虑到之前的回答中已经有一个MapperConfigManager类,用于重建SqlSessionFactory,我需要调整这个类,使其能够接受不同的路径参数,并在切换时正确应用新的路径。同时,需要确保在切换过程中,现有的数据库操作不会受到影响,可能需要暂停或重新初始化相关组件。 另外,引用[3]提到了@MapperScan可以配置不同的扫描地址,可能需要结合这个注解来动态调整Mapper接口的扫描路径,但用户的问题更关注XML文件的路径切换,所以可能不需要调整接口扫描,只需处理XML文件的位置。 需要注意,MyBatis在启动时会根据mapper-locations加载XML文件,并建立与Mapper接口的关联。动态切换时,需要重新加载这些XML文件,并更新对应的Mapper接口的代理对象。这可能需要清空缓存,并重新初始化SqlSessionFactory,如之前的回答所示。 还需要考虑不同数据库的映射文件可能存放在不同的目录下,比如mysqlMapperdamengmapper,这两个目录结构需要正确配置,确保在切换时路径正确,并且Ant风格的通配符能够正确匹配到所需的XML文件。 可能的步骤包括: 1. 创建一个配置管理器,存储当前使用的数据库类型(MySQL或达梦)。 2. 根据当前数据库类型,动态生成对应的mapper-locations路径。 3. 当切换数据库类型时,调用方法重建SqlSessionFactory,并应用新的mapper-locations。 4. 更新Mapper接口的代理对象,确保后续操作使用新的XML映射文件。 此外,需要处理可能的问题,如并发情况下的线程安全,确保在切换过程中不会有正在进行的数据库操作使用旧的映射文件,导致错误。可能需要使用锁机制或其他同步手段来保证切换的原子性。 还需要测试在切换后,原有的Mapper接口是否能够正确执行新的SQL映射,特别是不同数据库的语法差异是否被正确处理。例如,达梦数据库可能有不同的分页语法或函数,需要在对应的XML文件中定义,而切换后这些SQL语句应该生效。 最后,根据引用中的内容,需要注意classpath*classpath的区别,确保路径配置正确,能够正确加载到所需的XML文件。例如,使用classpath*:mapper/mysqlMapper/**/*Mapper.xml会搜索所有类路径下符合该模式的文件,而classpath:则只在第一个找到的类路径下搜索。 综上所述,解决方案需要结合动态配置管理、SqlSessionFactory的重建、路径切换以及线程安全处理,确保在不同数据库之间无缝切换映射文件。</think>### 基于多数据库的Mapper动态切换方案(MySQL/达梦) #### 一、技术架构设计 ```plantuml @startuml [应用层] --> [配置中心] [配置中心] --> |监听变更| [动态工厂] [动态工厂] --> |重建| [SqlSessionFactory] [SqlSessionFactory] --> |加载| MySQL_Mapper [SqlSessionFactory] --> |加载| Dameng_Mapper @enduml ``` #### 二、核心实现步骤 --- ### 1. 配置文件预定义路径模板 ```yaml # application.yml switchable: mapper-paths: mysql: "classpath*:mapper/mysqlMapper/**/*Mapper.xml" dameng: "classpath*:mapper/damengMapper/**/*Mapper.xml" ``` --- ### 2. 动态工厂增强实现 ```java public class DynamicMapperFactory { private final ThreadLocal<String> currentDbType = ThreadLocal.withInitial(() -> "mysql"); public void switchDatabase(String dbType) { currentDbType.set(dbType); refreshMappers(); } private String getActivePath() { return environment.getProperty("switchable.mapper-paths." + currentDbType.get()); } public void refreshMappers() { SqlSessionFactory newFactory = createSessionFactory(getActivePath()); updateFactoryInContext(newFactory); } private SqlSessionFactory createSessionFactory(String path) { MybatisPlusProperties properties = new MybatisPlusProperties(); properties.setMapperLocations(new String[]{path}); // 其他配置复制逻辑... } } ``` --- ### 3. 多路径扫描适配器 ```java @Configuration public class MultiPathMapperScanner { @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer configurer = new MapperScannerConfigurer(); configurer.setSqlSessionFactoryBeanName("dynamicSqlSessionFactory"); configurer.setBasePackage("com.yourpackage.mapper"); return configurer; } @Bean public SqlSessionFactory dynamicSqlSessionFactory() throws Exception { return new DynamicMapperFactory().buildFactory(); } } ``` --- ### 4. 数据库方言自动适配 ```java public class DynamicXMLMapperLoader { private static final Map<String, String> DB_DIALECT_MAP = new HashMap<>() {{ put("mysql", "mysqlMapper"); put("dameng", "damengMapper"); }}; public static String getMapperPath(String dbType) { return "classpath*:mapper/" + DB_DIALECT_MAP.get(dbType) + "/**/*Mapper.xml"; } } ``` --- ### 5. 安全切换控制器 ```java @RestController @RequestMapping("/config") public class MapperSwitchController { @Autowired private DynamicMapperFactory mapperFactory; @PostMapping("/switch-db") public ResponseEntity<?> switchDatabase(@RequestParam String dbType) { if (!Arrays.asList("mysql", "dameng").contains(dbType)) { return ResponseEntity.badRequest().body("无效的数据库类型"); } mapperFactory.switchDatabase(dbType); return ResponseEntity.ok(Map.of( "status", "success", "currentPath", mapperFactory.getActivePath() )); } } ``` --- ### 6. 映射文件目录结构示例 ``` resources/ ├─ mapper/ │ ├─ mysqlMapper/ │ │ ├─ user/ │ │ │ └─ UserMapper.xml │ │ └─ order/ │ │ └─ OrderMapper.xml │ └─ damengMapper/ │ ├─ user/ │ │ └─ UserMapper.xml │ └─ order/ │ └─ OrderMapper.xml ``` --- ### 三、关键配置说明 1. **路径通配符差异** - `classpath*:`:扫描所有JAR/WAR包中的匹配资源 - `**/`:匹配任意层级子目录 ```java // 示例路径解析 String mysqlPath = "classpath*:mapper/mysqlMapper/**/*Mapper.xml"; String damengPath = "classpath*:mapper/damengMapper/**/*Mapper.xml"; ``` 2. **版本兼容矩阵** | MyBatis-Plus版本 | 动态切换支持 | |----------------|------------| | 3.4.x | ✅ 完整支持 | | 3.5.x | ✅ 增强支持 | | 4.x | 🔧 需调整配置 | --- ### 四、操作验证流程 1. **初始状态检查** ```bash curl http://localhost:8080/config/current-path # 预期返回:"classpath*:mapper/mysqlMapper/**/*Mapper.xml" ``` 2. **执行切换操作** ```bash curl -X POST http://localhost:8080/config/switch-db?dbType=dameng ``` 3. **验证切换结果** ```java // 在DAO层注入查看 @Autowired private SqlSessionFactory sqlSessionFactory; public void printCurrentConfig() { Configuration config = sqlSessionFactory.getConfiguration(); config.getMappedStatements().forEach(ms -> System.out.println("Loaded Mapper: " + ms.getId())); } ``` --- ### 五、高级优化方案 1. **双缓冲机制** ```java public class DoubleBufferMapperFactory { private volatile SqlSessionFactory activeFactory; private SqlSessionFactory standbyFactory; public void switchFactory() { standbyFactory = createNewFactory(); activeFactory = standbyFactory; } } ``` 2. **版本化配置管理** ```yaml switchable: versioned-mappers: mysql-v1: "classpath*:mapper/mysql/v1/**/*.xml" mysql-v2: "classpath*:mapper/mysql/v2/**/*.xml" dameng-v1: "classpath*:mapper/dameng/v1/**/*.xml" ``` 3. **热加载监控看板** ```java @Scheduled(fixedRate = 5000) public void monitorMapperStatus() { Map<String, Integer> stats = sqlSessionFactory.getConfiguration() .getMappedStatements() .stream() .collect(Collectors.groupingBy( ms -> ms.getId().split("\\.")[2], // 提取mapper类别 Collectors.summingInt(e -> 1) )); // 推送到监控系统... } ``` --- ### 六、典型问题排查指南 | 现象 | 解决方案 | 相关引用 | |----------------------|---------------------------------|--------| | 切换后SQL未生效 | 检查`classpath*:`通配符格式是否正确 | [^1][^4] | | 事务上下文丢失 | 确保在切换前完成事务提交/回滚 | [^2] | | 部分Mapper未加载 | 验证路径层级匹配规则 | [^3][^5] | | 性能下降超过50% | 启用双缓冲机制减少重建耗时 | [^4] |
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

符华-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值