From d49db8eaa8b9fdc2df4716b9a15f7a14e8526d0b Mon Sep 17 00:00:00 2001 From: dhb52 Date: Tue, 18 Jun 2024 16:59:54 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20find=5Fin=5Fset=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E7=9A=84=E8=B7=A8=E6=95=B0=E6=8D=AE=E5=BA=93=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/core/enums/FindInSetEnum.java | 50 ++++++++++++++ .../mybatis/core/enums/NameToTypeEnum.java | 66 +++++++++++++++++++ .../mybatis/core/util/JdbcUtils.java | 24 +++++++ .../mybatis/core/util/MyBatisUtils.java | 21 +++++- 4 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/FindInSetEnum.java create mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/NameToTypeEnum.java diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/FindInSetEnum.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/FindInSetEnum.java new file mode 100644 index 0000000000..298d0dd9d1 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/FindInSetEnum.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.framework.mybatis.core.enums; + + +import com.baomidou.mybatisplus.annotation.DbType; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * find_in_set函数的跨数据库实现 + * + * @author dhb52 + */ +@Getter +@AllArgsConstructor +public enum FindInSetEnum { + + // FIND_IN_SET: MySQL 类型 + MYSQL("FIND_IN_SET('#{value}', #{column}) <> 0", DbType.MYSQL), + DM("FIND_IN_SET('#{value}', #{column}) <> 0", DbType.DM), + + // INSTR: Oracle 类型 + ORACLE("INSTR(','||#{column}||',' , ',#{value},') <> 0", DbType.ORACLE), + + // CHARINDEX: SQLServer + SQLSERVER("CHARINDEX(',' + #{value} + ',', ',' + #{column} + ',')", DbType.SQL_SERVER), + + // POSITION: PostgreSQL 类型 + POSTGRE_SQL("POSITION('#{value}' IN #{column})", DbType.POSTGRE_SQL), + KINGBASE_ES("POSITION('#{value}' IN #{column})", DbType.KINGBASE_ES), + + // LOCATE: 其他 + H2("LOCATE('#{value}' IN #{column})", DbType.H2), + ; + + public static final Map MAPS = Arrays.stream(values()) + .collect(Collectors.toMap(FindInSetEnum::getDbType, FindInSetEnum::getSqlTemplate)); + + private String sqlTemplate; + private DbType dbType; + + public static String getTemplate(DbType dbType) { + return Optional.of(MAPS.get(dbType)) + .orElseThrow(() -> new IllegalArgumentException("FIND_IN_SET not supported")); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/NameToTypeEnum.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/NameToTypeEnum.java new file mode 100644 index 0000000000..065f702e40 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/NameToTypeEnum.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.framework.mybatis.core.enums; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.annotation.DbType; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 数据库产品名 => mp DbType 的映射关系 + * + * @author dhb52 + */ +@Getter +@AllArgsConstructor +public enum NameToTypeEnum { + + /** + * MySQL + */ + MY_SQL("MySQL", DbType.MYSQL), + + /** + * Oracle + */ + ORACLE("Oracle", DbType.ORACLE), + + /** + * PostgreSQL + */ + POSTGRE_SQL("PostgreSQL", DbType.POSTGRE_SQL), + + /** + * SQL Server + */ + SQL_SERVER("Microsoft SQL Server", DbType.SQL_SERVER), + + /** + * 达梦 + */ + DM("DM DBMS", DbType.DM), + + /** + * 人大金仓 + */ + KINGBASE_ES("KingbaseES", DbType.KINGBASE_ES), + + // 华为openGauss ProductName 与 PostgreSQL相同 + ; + + private final String name; + private final DbType type; + + public static final Map MAPS = Arrays.stream(values()) + .collect(Collectors.toMap(NameToTypeEnum::getName, NameToTypeEnum::getType)); + + public static DbType find(String databaseProductName) { + if (StrUtil.isBlank(databaseProductName)) { + return null; + } + return MAPS.get(databaseProductName); + } +} \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java index b98a907c13..532162c2ad 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java @@ -1,9 +1,15 @@ package cn.iocoder.yudao.framework.mybatis.core.util; +import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; +import cn.iocoder.yudao.framework.mybatis.core.enums.NameToTypeEnum; +import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; import com.baomidou.mybatisplus.annotation.DbType; +import javax.sql.DataSource; import java.sql.Connection; +import java.sql.DatabaseMetaData; import java.sql.DriverManager; +import java.sql.SQLException; /** * JDBC 工具类 @@ -38,4 +44,22 @@ public class JdbcUtils { return com.baomidou.mybatisplus.extension.toolkit.JdbcUtils.getDbType(url); } + /** + * 通过当前数据库连接获得对应的 DB 类型 + * + * @return DB 类型 + */ + public static DbType getDbType() { + DynamicRoutingDataSource dynamicRoutingDataSource = SpringUtils.getBean(DynamicRoutingDataSource.class); + DataSource dataSource = dynamicRoutingDataSource.determineDataSource(); + try (Connection conn = dataSource.getConnection()) { + DatabaseMetaData metaData = conn.getMetaData(); + String databaseProductName = metaData.getDatabaseProductName(); + DbType dbType = NameToTypeEnum.find(databaseProductName); + return dbType; + } catch (SQLException e) { + throw new IllegalArgumentException(e.getMessage()); + } + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java index 3da059a6cc..789bf75c9d 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java @@ -1,8 +1,11 @@ package cn.iocoder.yudao.framework.mybatis.core.util; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.SortingField; +import cn.iocoder.yudao.framework.mybatis.core.enums.FindInSetEnum; +import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; @@ -34,7 +37,7 @@ public class MyBatisUtils { // 排序字段 if (!CollectionUtil.isEmpty(sortingFields)) { page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(sortingField.getOrder()) ? - OrderItem.asc(sortingField.getField()) : OrderItem.desc(sortingField.getField())) + OrderItem.asc(sortingField.getField()) : OrderItem.desc(sortingField.getField())) .collect(Collectors.toList())); } return page; @@ -56,7 +59,7 @@ public class MyBatisUtils { /** * 获得 Table 对应的表名 - * + *

* 兼容 MySQL 转义表名 `t_xxx` * * @param table 表 @@ -85,4 +88,18 @@ public class MyBatisUtils { return new Column(tableName + StringPool.DOT + column); } + /** + * 跨数据库的 find_in_set 实现 + * + * @param column 字段名称 + * @param value 查询值(不带单引号) + * @return sql + */ + public static String findInSet(String column, Object value) { + // 这里不用SqlConstants.DB_TYPE,因为它是使用 primary 数据源的 url 推断出来的类型 + DbType dbType = JdbcUtils.getDbType(); + return FindInSetEnum.getTemplate(dbType) + .replace("#{column}", column) + .replace("#{value}", StrUtil.toString(value)); + } } From ad03872844f69392f2718d8c50fa304389336b92 Mon Sep 17 00:00:00 2001 From: dhb52 Date: Tue, 18 Jun 2024 17:09:39 +0800 Subject: [PATCH 2/2] =?UTF-8?q?doc:=20=E6=9B=B4=E6=96=B0=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=20docker=20=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/tools/README.md | 11 +++++------ sql/tools/docker-compose.yaml | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/sql/tools/README.md b/sql/tools/README.md index 957a807bb6..c053652316 100644 --- a/sql/tools/README.md +++ b/sql/tools/README.md @@ -55,7 +55,7 @@ docker load -i dm8_20230808_rev197096_x86_rh6_64_single.tar ```Bash docker compose up -d dm8 # 注意:启动完 dm 后,需要手动再执行如下命令,因为 dm 不支持初始化脚本 -docker compose exec dm8 bash -c "exec /opt/dmdbms/bin/disql SYSDBA/SYSDBA001 \`/tmp/schema.sql" +docker compose exec dm8 bash -c '/opt/dmdbms/bin/disql SYSDBA/SYSDBA001 \`/tmp/schema.sql' exit ``` @@ -67,7 +67,8 @@ exit ① 下载人大金仓 Docker 镜像: -> x86_64 版本: https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/x86_64/kdb_x86_64_V009R001C001B0025.tar +> x86_64 版本: https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/x86_64/kdb_x86_64_V009R001C001B0025.tar + > aarch64 版本:https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/aarch64/kdb_aarch64_V009R001C001B0025.tar ② 加载镜像文件,在镜像 tar 文件所在目录运行: @@ -80,12 +81,10 @@ docker load -i x86_64/kdb_x86_64_V009R001C001B0025.tar ```Bash docker compose up -d kingbase -# 注意:启动完 kingbase 后,需要手动再执行如下命令,因为 dm 不支持初始化脚本 -docker compose exec kingbase bash -c "exec ksql -Uroot -d test -f /tmp/schema.sql" +# 注意:启动完 kingbase 后,需要手动再执行如下命令 +docker compose exec kingbase bash -c 'ksql -U $DB_USER -d test -f /tmp/schema.sql' ``` -**注意**: MyBatis、MyBatis Plus 目前不兼容人大金仓,推荐直接使用 PostgreSQL JDBC 驱动,已经 url 配置方式连接数据库。 - ### 1.7 华为 OpenGauss ```Bash diff --git a/sql/tools/docker-compose.yaml b/sql/tools/docker-compose.yaml index 232ad98c3f..d6f615d093 100644 --- a/sql/tools/docker-compose.yaml +++ b/sql/tools/docker-compose.yaml @@ -93,7 +93,7 @@ services: volumes: - dm8:/opt/dmdbms/data - ../dm/ruoyi-vue-pro-dm8.sql:/tmp/schema.sql:ro - # docker compose exec dm8 bash -c "exec /opt/dmdbms/bin/disql SYSDBA/SYSDBA001 \`/tmp/schema.sql" + # docker compose exec dm8 bash -c '/opt/dmdbms/bin/disql SYSDBA/SYSDBA001 \`/tmp/schema.sql' kingbase: # x86_64: https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/x86_64/kdb_x86_64_V009R001C001B0025.tar