Springboot项目之mybatis-plus多容器分布式部署id重复问题之源码解析

mybatis-plus 3.3.2 部署多个pod id冲突问题

配置:

复制代码
# 设置随机
mybatis-plus.global-config.worker-id: ${random.int(1,31)}
mybatis-plus.global-config.datacenter-id: ${random.int(1,31)}

源码解析:MybatisSqlSessionFactoryBean

重点:new MybatisSqlSessionFactoryBuilder().build(targetConfiguration); -->IdWorker.setIdentifierGenerator(identifierGenerator);

java 复制代码
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {

    final MybatisConfiguration targetConfiguration;

    // TODO 使用 MybatisXmlConfigBuilder 而不是 XMLConfigBuilder
    MybatisXMLConfigBuilder xmlConfigBuilder = null;
    if (this.configuration != null) {
        targetConfiguration = this.configuration;
        if (targetConfiguration.getVariables() == null) {
            targetConfiguration.setVariables(this.configurationProperties);
        } else if (this.configurationProperties != null) {
            targetConfiguration.getVariables().putAll(this.configurationProperties);
        }
    } else if (this.configLocation != null) {
        // TODO 使用 MybatisXMLConfigBuilder
        xmlConfigBuilder = new MybatisXMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
        targetConfiguration = xmlConfigBuilder.getConfiguration();
    } else {
        LOGGER.debug(() -> "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration");
        // TODO 使用 MybatisConfiguration
        targetConfiguration = new MybatisConfiguration();
        Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
    }

    // TODO 无配置启动所必须的
    this.globalConfig = Optional.ofNullable(this.globalConfig).orElseGet(GlobalConfigUtils::defaults);
    this.globalConfig.setDbConfig(Optional.ofNullable(this.globalConfig.getDbConfig()).orElseGet(GlobalConfig.DbConfig::new));

    // TODO 初始化 id-work 以及 打印骚东西
    targetConfiguration.setGlobalConfig(this.globalConfig);

    // TODO 自定义枚举类扫描处理
    if (hasLength(this.typeEnumsPackage)) {
        Set<Class<?>> classes;
        if (typeEnumsPackage.contains(StringPool.STAR) && !typeEnumsPackage.contains(StringPool.COMMA)
            && !typeEnumsPackage.contains(StringPool.SEMICOLON)) {
            classes = scanClasses(typeEnumsPackage, null);
            if (classes.isEmpty()) {
                LOGGER.warn(() -> "Can't find class in '[" + typeEnumsPackage + "]' package. Please check your configuration.");
            }
        } else {
            classes = new HashSet<>();
            String[] typeEnumsPackageArray = tokenizeToStringArray(this.typeEnumsPackage,
                ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
            Assert.notNull(typeEnumsPackageArray, "not find typeEnumsPackage:" + typeEnumsPackage);
            Stream.of(typeEnumsPackageArray).forEach(typePackage -> {
                try {
                    Set<Class<?>> scanTypePackage = scanClasses(typePackage, null);
                    if (scanTypePackage.isEmpty()) {
                        LOGGER.warn(() -> "Can't find class in '[" + typePackage + "]' package. Please check your configuration.");
                    } else {
                        classes.addAll(scanTypePackage);
                    }
                } catch (IOException e) {
                    throw new MybatisPlusException("Cannot scan class in '[" + typePackage + "]' package", e);
                }
            });
        }
        // 取得类型转换注册器
        TypeHandlerRegistry typeHandlerRegistry = targetConfiguration.getTypeHandlerRegistry();
        classes.stream()
            .filter(Class::isEnum)
            .filter(MybatisEnumTypeHandler::isMpEnums)
            .forEach(cls -> typeHandlerRegistry.register(cls, MybatisEnumTypeHandler.class));
    }

    Optional.ofNullable(this.objectFactory).ifPresent(targetConfiguration::setObjectFactory);
    Optional.ofNullable(this.objectWrapperFactory).ifPresent(targetConfiguration::setObjectWrapperFactory);
    Optional.ofNullable(this.vfs).ifPresent(targetConfiguration::setVfsImpl);

    if (hasLength(this.typeAliasesPackage)) {
        scanClasses(this.typeAliasesPackage, this.typeAliasesSuperType).stream()
            .filter(clazz -> !clazz.isAnonymousClass()).filter(clazz -> !clazz.isInterface())
            .filter(clazz -> !clazz.isMemberClass()).forEach(targetConfiguration.getTypeAliasRegistry()::registerAlias);
    }

    if (!isEmpty(this.typeAliases)) {
        Stream.of(this.typeAliases).forEach(typeAlias -> {
            targetConfiguration.getTypeAliasRegistry().registerAlias(typeAlias);
            LOGGER.debug(() -> "Registered type alias: '" + typeAlias + "'");
        });
    }

    if (!isEmpty(this.plugins)) {
        Stream.of(this.plugins).forEach(plugin -> {
            targetConfiguration.addInterceptor(plugin);
            LOGGER.debug(() -> "Registered plugin: '" + plugin + "'");
        });
    }

    if (hasLength(this.typeHandlersPackage)) {
        scanClasses(this.typeHandlersPackage, TypeHandler.class).stream().filter(clazz -> !clazz.isAnonymousClass())
            .filter(clazz -> !clazz.isInterface()).filter(clazz -> !Modifier.isAbstract(clazz.getModifiers()))
            .forEach(targetConfiguration.getTypeHandlerRegistry()::register);
    }

    if (!isEmpty(this.typeHandlers)) {
        Stream.of(this.typeHandlers).forEach(typeHandler -> {
            targetConfiguration.getTypeHandlerRegistry().register(typeHandler);
            LOGGER.debug(() -> "Registered type handler: '" + typeHandler + "'");
        });
    }

    if (!isEmpty(this.scriptingLanguageDrivers)) {
        Stream.of(this.scriptingLanguageDrivers).forEach(languageDriver -> {
            targetConfiguration.getLanguageRegistry().register(languageDriver);
            LOGGER.debug(() -> "Registered scripting language driver: '" + languageDriver + "'");
        });
    }

    Optional.ofNullable(this.defaultScriptingLanguageDriver).ifPresent(targetConfiguration::setDefaultScriptingLanguage);

    if (this.databaseIdProvider != null) {// fix #64 set databaseId before parse mapper xmls
        try {
            targetConfiguration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
        } catch (SQLException e) {
            throw new NestedIOException("Failed getting a databaseId", e);
        }
    }

    Optional.ofNullable(this.cache).ifPresent(targetConfiguration::addCache);

    if (xmlConfigBuilder != null) {
        try {
            xmlConfigBuilder.parse();
            LOGGER.debug(() -> "Parsed configuration file: '" + this.configLocation + "'");
        } catch (Exception ex) {
            throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);
        } finally {
            ErrorContext.instance().reset();
        }
    }

    targetConfiguration.setEnvironment(new Environment(MybatisSqlSessionFactoryBean.class.getSimpleName(),
        this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory,
        this.dataSource));

    if (this.mapperLocations != null) {
        if (this.mapperLocations.length == 0) {
            LOGGER.warn(() -> "Property 'mapperLocations' was specified but matching resources are not found.");
        } else {
            for (Resource mapperLocation : this.mapperLocations) {
                if (mapperLocation == null) {
                    continue;
                }
                try {
                    XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
                        targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
                    xmlMapperBuilder.parse();
                } catch (Exception e) {
                    throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
                } finally {
                    ErrorContext.instance().reset();
                }
                LOGGER.debug(() -> "Parsed mapper file: '" + mapperLocation + "'");
            }
        }
    } else {
        LOGGER.debug(() -> "Property 'mapperLocations' was not specified.");
    }

    final SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(targetConfiguration);

    // TODO SqlRunner
    SqlHelper.FACTORY = sqlSessionFactory;

    // TODO 打印骚东西 Banner
    if (globalConfig.isBanner()) {
        System.out.println(" _ _   |_  _ _|_. ___ _ |    _ ");
        System.out.println("| | |\\/|_)(_| | |_\\  |_)||_|_\\ ");
        System.out.println("     /               |         ");
        System.out.println("                        " + MybatisPlusVersion.getVersion() + " ");
    }

    return sqlSessionFactory;
}

idworker实战

其中mybatis-plus内置的ImadcnIdentifierGenerator方法,就已经提供了对idworker框架的支持。

升级版本:v3.4.0

复制代码
  " + MybatisPlusVersion.getVersion() + " ");
}

return sqlSessionFactory;

}

复制代码
# idworker实战

其中mybatis-plus内置的`ImadcnIdentifierGenerator`方法,就已经提供了对idworker框架的支持。

升级版本:v3.4.0

![在这里插入图片描述](https://img-blog.csdnimg.cn/img_convert/6aac34ebf0f36867d15d889d56f55fd7.png)
相关推荐
二哈喇子!3 小时前
SpringBoot项目右上角选择ProjectNameApplication的配置
java·spring boot
sin22014 小时前
MyBatis的执行流程
java·开发语言·mybatis
二哈喇子!4 小时前
基于Spring Boot框架的车库停车管理系统的设计与实现
java·spring boot·后端·计算机毕业设计
二哈喇子!4 小时前
基于SpringBoot框架的水之森海底世界游玩系统
spring boot·旅游
二哈喇子!4 小时前
Java框架精品项目【用于个人学习】
java·spring boot·学习
二哈喇子!5 小时前
基于SpringBoot框架的网上购书系统的设计与实现
java·大数据·spring boot
二哈喇子!5 小时前
基于JavaSE的淘宝卖鞋后端管理系统的设计与实现
java·spring boot·spring
Coder_Boy_5 小时前
基于SpringAI的在线考试系统-智能考试系统-学习分析模块
java·开发语言·数据库·spring boot·ddd·tdd
天天进步20156 小时前
多线程与分布式:使用 Botasaurus 轻松构建大规模数据采集集群
分布式·爬虫
高山上有一只小老虎6 小时前
mybatisplus实现分页查询
java·spring boot·mybatis