mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 10:37:41 +08:00 
			
		
		
		
	封装 IdTypeEnvironmentPostProcessor 组件,自动适配 id-type 策略,用于 Oracle、PostgreSQL 的自动适配
This commit is contained in:
		| @ -42,6 +42,10 @@ | ||||
|             <groupId>com.oracle.database.jdbc</groupId> | ||||
|             <artifactId>ojdbc8</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.postgresql</groupId> | ||||
|             <artifactId>postgresql</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.alibaba</groupId> | ||||
|  | ||||
| @ -0,0 +1,73 @@ | ||||
| package cn.iocoder.yudao.framework.mybatis.config; | ||||
|  | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; | ||||
| import com.baomidou.mybatisplus.annotation.DbType; | ||||
| import com.baomidou.mybatisplus.annotation.IdType; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.env.EnvironmentPostProcessor; | ||||
| import org.springframework.core.env.ConfigurableEnvironment; | ||||
|  | ||||
| import java.util.Set; | ||||
|  | ||||
| /** | ||||
|  * 当 IdType 为 {@link IdType#NONE} 时,根据 PRIMARY 数据源所使用的数据库,自动设置 | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| @Slf4j | ||||
| public class IdTypeEnvironmentPostProcessor implements EnvironmentPostProcessor { | ||||
|  | ||||
|     private static final String ID_TYPE_KEY = "mybatis-plus.global-config.db-config.id-type"; | ||||
|  | ||||
|     private static final String DATASOURCE_DYNAMIC_KEY = "spring.datasource.dynamic"; | ||||
|  | ||||
|     private static final Set<DbType> INPUT_ID_TYPES = SetUtils.asSet(DbType.ORACLE, DbType.ORACLE_12C, | ||||
|             DbType.POSTGRE_SQL, DbType.KINGBASE_ES, DbType.DB2, DbType.H2); | ||||
|  | ||||
|     @Override | ||||
|     public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { | ||||
|         // 如果非 NONE,则不进行处理 | ||||
|         IdType idType = getIdType(environment); | ||||
|         if (idType != IdType.NONE) { | ||||
|             return; | ||||
|         } | ||||
|         // 如果获取不到 DbType,则不进行处理 | ||||
|         DbType dbType = getDbType(environment); | ||||
|         if (dbType == null) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 情况一,用户输入 ID,适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库 | ||||
|         if (INPUT_ID_TYPES.contains(dbType)) { | ||||
|             setIdType(environment, IdType.INPUT); | ||||
|             return; | ||||
|         } | ||||
|         // 情况二,自增 ID,适合 MySQL 等直接自增的数据库 | ||||
|         setIdType(environment, IdType.AUTO); | ||||
|     } | ||||
|  | ||||
|     public IdType getIdType(ConfigurableEnvironment environment) { | ||||
|         return environment.getProperty(ID_TYPE_KEY, IdType.class); | ||||
|     } | ||||
|  | ||||
|     public void setIdType(ConfigurableEnvironment environment, IdType idType) { | ||||
|         environment.getSystemProperties().put(ID_TYPE_KEY, idType); | ||||
|         log.info("[setIdType][修改 MyBatis Plus 的 idType 为({})]", idType); | ||||
|     } | ||||
|  | ||||
|     public static DbType getDbType(ConfigurableEnvironment environment) { | ||||
|         String primary = environment.getProperty(DATASOURCE_DYNAMIC_KEY + "." + "primary"); | ||||
|         if (StrUtil.isEmpty(primary)) { | ||||
|             return null; | ||||
|         } | ||||
|         String url = environment.getProperty(DATASOURCE_DYNAMIC_KEY + ".datasource." + primary + ".url"); | ||||
|         if (StrUtil.isEmpty(url)) { | ||||
|             return null; | ||||
|         } | ||||
|         return JdbcUtils.getDbType(url); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -1,13 +1,22 @@ | ||||
| package cn.iocoder.yudao.framework.mybatis.config; | ||||
|  | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.handler.DefaultDBFieldHandler; | ||||
| import com.baomidou.mybatisplus.annotation.DbType; | ||||
| import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; | ||||
| import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator; | ||||
| import com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator; | ||||
| import com.baomidou.mybatisplus.extension.incrementer.KingbaseKeyGenerator; | ||||
| import com.baomidou.mybatisplus.extension.incrementer.OracleKeyGenerator; | ||||
| import com.baomidou.mybatisplus.extension.incrementer.PostgreKeyGenerator; | ||||
| import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; | ||||
| import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
| import org.mybatis.spring.annotation.MapperScan; | ||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.core.env.ConfigurableEnvironment; | ||||
|  | ||||
| /** | ||||
|  * MyBaits 配置类 | ||||
| @ -31,4 +40,25 @@ public class YudaoMybatisAutoConfiguration { | ||||
|         return new DefaultDBFieldHandler(); // 自动填充参数类 | ||||
|     } | ||||
|  | ||||
|     @Bean | ||||
|     @ConditionalOnProperty(prefix = "mybatis-plus.global-config.db-config", name = "id-type", havingValue = "INPUT") | ||||
|     public IKeyGenerator keyGenerator(ConfigurableEnvironment environment) { | ||||
|         DbType dbType = IdTypeEnvironmentPostProcessor.getDbType(environment); | ||||
|         if (dbType != null) { | ||||
|             switch (dbType) { | ||||
|                 case POSTGRE_SQL: | ||||
|                     return new PostgreKeyGenerator(); | ||||
|                 case ORACLE: | ||||
|                 case ORACLE_12C: | ||||
|                     return new OracleKeyGenerator(); | ||||
|                 case H2: | ||||
|                     return new H2KeyGenerator(); | ||||
|                 case KINGBASE_ES: | ||||
|                     return new KingbaseKeyGenerator(); | ||||
|             } | ||||
|         } | ||||
|         // 找不到合适的 IKeyGenerator 实现类 | ||||
|         throw new IllegalArgumentException(StrUtil.format("DbType{} 找不到合适的 IKeyGenerator 实现类", dbType)); | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,7 @@ | ||||
| package cn.iocoder.yudao.framework.mybatis.core.util; | ||||
|  | ||||
| import com.baomidou.mybatisplus.annotation.DbType; | ||||
|  | ||||
| import java.sql.Connection; | ||||
| import java.sql.DriverManager; | ||||
|  | ||||
| @ -26,4 +28,15 @@ public class JdbcUtils { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获得 URL 对应的 DB 类型 | ||||
|      * | ||||
|      * @param url URL | ||||
|      * @return DB 类型 | ||||
|      */ | ||||
|     public static DbType getDbType(String url) { | ||||
|         String name = com.alibaba.druid.util.JdbcUtils.getDbType(url, null); | ||||
|         return DbType.getDbType(name); | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| @ -1,3 +1,5 @@ | ||||
| org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ | ||||
|   cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration,\ | ||||
|   cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration | ||||
| org.springframework.boot.env.EnvironmentPostProcessor=\ | ||||
|   cn.iocoder.yudao.framework.mybatis.config.IdTypeEnvironmentPostProcessor | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| package cn.iocoder.yudao.module.system.framework.errorcode.core.generator; | ||||
|  | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.exceptions.ExceptionUtil; | ||||
| import cn.hutool.core.util.ClassUtil; | ||||
| import cn.hutool.core.util.ReflectUtil; | ||||
| import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||||
| @ -67,10 +68,15 @@ public class ErrorCodeAutoGeneratorImpl implements ErrorCodeAutoGenerator { | ||||
|         // 解析错误码 | ||||
|         List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs = new ArrayList<>(); | ||||
|         constantsClassList.forEach(constantsClass -> { | ||||
|             try { | ||||
|                 // 解析错误码枚举类 | ||||
|                 Class<?> errorCodeConstantsClazz = ClassUtil.loadClass(constantsClass); | ||||
|                 // 解析错误码 | ||||
|                 autoGenerateDTOs.addAll(parseErrorCode(errorCodeConstantsClazz)); | ||||
|             } catch (Exception ex) { | ||||
|                 log.warn("[parseErrorCode][constantsClass({}) 加载失败({})]", constantsClass, | ||||
|                         ExceptionUtil.getRootCauseMessage(ex)); | ||||
|             } | ||||
|         }); | ||||
|         return autoGenerateDTOs; | ||||
|     } | ||||
|  | ||||
| @ -43,11 +43,11 @@ | ||||
|             <version>${revision}</version> | ||||
|         </dependency> | ||||
|         <!-- 默认引入 yudao-module-bpm-biz-flowable 实现,可以替换为 yudao-module-bpm-biz-activiti 实现--> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-module-bpm-biz-flowable</artifactId> | ||||
|             <version>${revision}</version> | ||||
|         </dependency> | ||||
| <!--        <dependency>--> | ||||
| <!--            <groupId>cn.iocoder.boot</groupId>--> | ||||
| <!--            <artifactId>yudao-module-bpm-biz-flowable</artifactId>--> | ||||
| <!--            <version>${revision}</version>--> | ||||
| <!--        </dependency>--> | ||||
| <!--        <dependency>--> | ||||
| <!--            <groupId>cn.iocoder.boot</groupId>--> | ||||
| <!--            <artifactId>yudao-module-bpm-biz-activiti</artifactId>--> | ||||
|  | ||||
| @ -36,7 +36,7 @@ spring: | ||||
|         time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 | ||||
|         min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 | ||||
|         max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 | ||||
|         validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 | ||||
|         validation-query: SELECT 1 # 配置检测连接是否有效 | ||||
|         test-while-idle: true | ||||
|         test-on-borrow: false | ||||
|         test-on-return: false | ||||
|  | ||||
| @ -36,7 +36,7 @@ spring: | ||||
|         time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 | ||||
|         min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 | ||||
|         max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 | ||||
|         validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 | ||||
|         validation-query: SELECT 1 # 配置检测连接是否有效 | ||||
|         test-while-idle: true | ||||
|         test-on-borrow: false | ||||
|         test-on-return: false | ||||
| @ -44,14 +44,14 @@ spring: | ||||
|       datasource: | ||||
|         master: | ||||
|           name: ruoyi-vue-pro | ||||
|           url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||||
|           driver-class-name: com.mysql.jdbc.Driver | ||||
| #          url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL 连接的示例 | ||||
|           url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 | ||||
|           username: root | ||||
|           password: 123456 | ||||
|         slave: # 模拟从库,可根据自己需要修改 | ||||
|           name: ruoyi-vue-pro | ||||
|           url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||||
|           driver-class-name: com.mysql.jdbc.Driver | ||||
| #          url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL 连接的示例 | ||||
|           url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 | ||||
|           username: root | ||||
|           password: 123456 | ||||
|  | ||||
|  | ||||
| @ -54,7 +54,10 @@ mybatis-plus: | ||||
|     map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 | ||||
|   global-config: | ||||
|     db-config: | ||||
|       id-type: AUTO # 自增 ID | ||||
|       id-type: NONE # “智能”模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。 | ||||
| #      id-type: AUTO # 自增 ID,适合 MySQL 等直接自增的数据库 | ||||
| #      id-type: INPUT # 用户输入 ID,适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库 | ||||
| #      id-type: ASSIGN_ID # 分配 ID,默认使用雪花算法。注意,Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解 | ||||
|       logic-delete-value: 1 # 逻辑已删除值(默认为 1) | ||||
|       logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) | ||||
|   type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV