mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	封装 IdTypeEnvironmentPostProcessor 组件,自动适配 id-type 策略,用于 Oracle、PostgreSQL 的自动适配
This commit is contained in:
		| @@ -42,6 +42,10 @@ | |||||||
|             <groupId>com.oracle.database.jdbc</groupId> |             <groupId>com.oracle.database.jdbc</groupId> | ||||||
|             <artifactId>ojdbc8</artifactId> |             <artifactId>ojdbc8</artifactId> | ||||||
|         </dependency> |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.postgresql</groupId> | ||||||
|  |             <artifactId>postgresql</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>com.alibaba</groupId> |             <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; | package cn.iocoder.yudao.framework.mybatis.config; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.util.StrUtil; | ||||||
| import cn.iocoder.yudao.framework.mybatis.core.handler.DefaultDBFieldHandler; | 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.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.MybatisPlusInterceptor; | ||||||
| import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; | ||||||
| import org.apache.ibatis.annotations.Mapper; | import org.apache.ibatis.annotations.Mapper; | ||||||
| import org.mybatis.spring.annotation.MapperScan; | import org.mybatis.spring.annotation.MapperScan; | ||||||
|  | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||||||
| import org.springframework.context.annotation.Bean; | import org.springframework.context.annotation.Bean; | ||||||
| import org.springframework.context.annotation.Configuration; | import org.springframework.context.annotation.Configuration; | ||||||
|  | import org.springframework.core.env.ConfigurableEnvironment; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * MyBaits 配置类 |  * MyBaits 配置类 | ||||||
| @@ -31,4 +40,25 @@ public class YudaoMybatisAutoConfiguration { | |||||||
|         return new DefaultDBFieldHandler(); // 自动填充参数类 |         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; | package cn.iocoder.yudao.framework.mybatis.core.util; | ||||||
|  |  | ||||||
|  | import com.baomidou.mybatisplus.annotation.DbType; | ||||||
|  |  | ||||||
| import java.sql.Connection; | import java.sql.Connection; | ||||||
| import java.sql.DriverManager; | 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=\ | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ | ||||||
|   cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration,\ |   cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration,\ | ||||||
|   cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration |   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; | package cn.iocoder.yudao.module.system.framework.errorcode.core.generator; | ||||||
|  |  | ||||||
| import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||||
|  | import cn.hutool.core.exceptions.ExceptionUtil; | ||||||
| import cn.hutool.core.util.ClassUtil; | import cn.hutool.core.util.ClassUtil; | ||||||
| import cn.hutool.core.util.ReflectUtil; | import cn.hutool.core.util.ReflectUtil; | ||||||
| import cn.iocoder.yudao.framework.common.exception.ErrorCode; | import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||||||
| @@ -67,10 +68,15 @@ public class ErrorCodeAutoGeneratorImpl implements ErrorCodeAutoGenerator { | |||||||
|         // 解析错误码 |         // 解析错误码 | ||||||
|         List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs = new ArrayList<>(); |         List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs = new ArrayList<>(); | ||||||
|         constantsClassList.forEach(constantsClass -> { |         constantsClassList.forEach(constantsClass -> { | ||||||
|  |             try { | ||||||
|                 // 解析错误码枚举类 |                 // 解析错误码枚举类 | ||||||
|                 Class<?> errorCodeConstantsClazz = ClassUtil.loadClass(constantsClass); |                 Class<?> errorCodeConstantsClazz = ClassUtil.loadClass(constantsClass); | ||||||
|                 // 解析错误码 |                 // 解析错误码 | ||||||
|                 autoGenerateDTOs.addAll(parseErrorCode(errorCodeConstantsClazz)); |                 autoGenerateDTOs.addAll(parseErrorCode(errorCodeConstantsClazz)); | ||||||
|  |             } catch (Exception ex) { | ||||||
|  |                 log.warn("[parseErrorCode][constantsClass({}) 加载失败({})]", constantsClass, | ||||||
|  |                         ExceptionUtil.getRootCauseMessage(ex)); | ||||||
|  |             } | ||||||
|         }); |         }); | ||||||
|         return autoGenerateDTOs; |         return autoGenerateDTOs; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -43,11 +43,11 @@ | |||||||
|             <version>${revision}</version> |             <version>${revision}</version> | ||||||
|         </dependency> |         </dependency> | ||||||
|         <!-- 默认引入 yudao-module-bpm-biz-flowable 实现,可以替换为 yudao-module-bpm-biz-activiti 实现--> |         <!-- 默认引入 yudao-module-bpm-biz-flowable 实现,可以替换为 yudao-module-bpm-biz-activiti 实现--> | ||||||
|         <dependency> | <!--        <dependency>--> | ||||||
|             <groupId>cn.iocoder.boot</groupId> | <!--            <groupId>cn.iocoder.boot</groupId>--> | ||||||
|             <artifactId>yudao-module-bpm-biz-flowable</artifactId> | <!--            <artifactId>yudao-module-bpm-biz-flowable</artifactId>--> | ||||||
|             <version>${revision}</version> | <!--            <version>${revision}</version>--> | ||||||
|         </dependency> | <!--        </dependency>--> | ||||||
| <!--        <dependency>--> | <!--        <dependency>--> | ||||||
| <!--            <groupId>cn.iocoder.boot</groupId>--> | <!--            <groupId>cn.iocoder.boot</groupId>--> | ||||||
| <!--            <artifactId>yudao-module-bpm-biz-activiti</artifactId>--> | <!--            <artifactId>yudao-module-bpm-biz-activiti</artifactId>--> | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ spring: | |||||||
|         time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 |         time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 | ||||||
|         min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 |         min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 | ||||||
|         max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 |         max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 | ||||||
|         validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 |         validation-query: SELECT 1 # 配置检测连接是否有效 | ||||||
|         test-while-idle: true |         test-while-idle: true | ||||||
|         test-on-borrow: false |         test-on-borrow: false | ||||||
|         test-on-return: false |         test-on-return: false | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ spring: | |||||||
|         time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 |         time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 | ||||||
|         min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 |         min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 | ||||||
|         max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 |         max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 | ||||||
|         validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 |         validation-query: SELECT 1 # 配置检测连接是否有效 | ||||||
|         test-while-idle: true |         test-while-idle: true | ||||||
|         test-on-borrow: false |         test-on-borrow: false | ||||||
|         test-on-return: false |         test-on-return: false | ||||||
| @@ -44,14 +44,14 @@ spring: | |||||||
|       datasource: |       datasource: | ||||||
|         master: |         master: | ||||||
|           name: ruoyi-vue-pro |           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 | #          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 连接的示例 | ||||||
|           driver-class-name: com.mysql.jdbc.Driver |           url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 | ||||||
|           username: root |           username: root | ||||||
|           password: 123456 |           password: 123456 | ||||||
|         slave: # 模拟从库,可根据自己需要修改 |         slave: # 模拟从库,可根据自己需要修改 | ||||||
|           name: ruoyi-vue-pro |           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 | #          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 连接的示例 | ||||||
|           driver-class-name: com.mysql.jdbc.Driver |           url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 | ||||||
|           username: root |           username: root | ||||||
|           password: 123456 |           password: 123456 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -54,7 +54,10 @@ mybatis-plus: | |||||||
|     map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 |     map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 | ||||||
|   global-config: |   global-config: | ||||||
|     db-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-delete-value: 1 # 逻辑已删除值(默认为 1) | ||||||
|       logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) |       logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) | ||||||
|   type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject |   type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV