From 6cd11eeb9a3ec65481aa29d4352e1995f88fb276 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 22 Feb 2024 12:03:59 +0800 Subject: [PATCH] add dm dialect --- hutool-db/pom.xml | 6 + .../hutool/db/dialect/DialectFactory.java | 2 + .../hutool/db/dialect/DialectName.java | 2 +- .../hutool/db/dialect/DriverNamePool.java | 4 +- .../hutool/db/dialect/impl/DmDialect.java | 108 ++++++++++++++++++ .../java/org/dromara/hutool/db/DmTest.java | 37 ++++++ 6 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 hutool-db/src/main/java/org/dromara/hutool/db/dialect/impl/DmDialect.java create mode 100644 hutool-db/src/test/java/org/dromara/hutool/db/DmTest.java diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 95d236496..4f245e097 100755 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -141,6 +141,12 @@ 2.2.224 test + + com.dameng + DmJdbcDriver18 + 8.1.3.62 + test + org.slf4j slf4j-simple diff --git a/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DialectFactory.java b/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DialectFactory.java index 84b0392d8..1dde6a074 100644 --- a/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DialectFactory.java +++ b/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DialectFactory.java @@ -72,6 +72,8 @@ public class DialectFactory implements DriverNamePool { return new SqlServer2012Dialect(dbConfig); } else if (DRIVER_PHOENIX.equalsIgnoreCase(driverName)) { return new PhoenixDialect(dbConfig); + } else if (DRIVER_DM.equalsIgnoreCase(driverName)) { + return new DmDialect(dbConfig); } } // 无法识别可支持的数据库类型默认使用ANSI方言,可兼容大部分SQL语句 diff --git a/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DialectName.java b/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DialectName.java index 0bdfc0756..a42039568 100644 --- a/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DialectName.java +++ b/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DialectName.java @@ -21,7 +21,7 @@ import org.dromara.hutool.core.text.StrUtil; * @author Looly */ public enum DialectName { - ANSI, MYSQL, ORACLE, POSTGRESQL, SQLITE3, H2, SQLSERVER, SQLSERVER2012, PHOENIX; + ANSI, MYSQL, ORACLE, POSTGRESQL, SQLITE3, H2, SQLSERVER, SQLSERVER2012, PHOENIX, DM; /** * 是否为指定数据库方言,检查时不分区大小写 diff --git a/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DriverNamePool.java b/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DriverNamePool.java index 3ea8a1e8f..5d6307746 100644 --- a/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DriverNamePool.java +++ b/hutool-db/src/main/java/org/dromara/hutool/db/dialect/DriverNamePool.java @@ -73,9 +73,9 @@ public interface DriverNamePool { */ String DRIVER_HSQLDB = "org.hsqldb.jdbc.JDBCDriver"; /** - * JDBC 驱动 达梦7 + * JDBC 驱动 达梦 */ - String DRIVER_DM7 = "dm.jdbc.driver.DmDriver"; + String DRIVER_DM = "dm.jdbc.driver.DmDriver"; /** * JDBC 驱动 人大金仓 */ diff --git a/hutool-db/src/main/java/org/dromara/hutool/db/dialect/impl/DmDialect.java b/hutool-db/src/main/java/org/dromara/hutool/db/dialect/impl/DmDialect.java new file mode 100644 index 000000000..5428f7714 --- /dev/null +++ b/hutool-db/src/main/java/org/dromara/hutool/db/dialect/impl/DmDialect.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.db.dialect.impl; + +import org.dromara.hutool.core.lang.Assert; +import org.dromara.hutool.core.text.StrUtil; +import org.dromara.hutool.db.Entity; +import org.dromara.hutool.db.config.DbConfig; +import org.dromara.hutool.db.dialect.DialectName; +import org.dromara.hutool.db.sql.QuoteWrapper; +import org.dromara.hutool.db.sql.SqlBuilder; +import org.dromara.hutool.db.sql.StatementUtil; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.util.Arrays; +import java.util.List; + +/** + * 达梦数据库方言 + * + * @author wb04307201 + */ +public class DmDialect extends AnsiSqlDialect { + private static final long serialVersionUID = 3415348435502927423L; + + /** + * 构造 + * + * @param dbConfig 数据库配置 + */ + public DmDialect(final DbConfig dbConfig) { + super(dbConfig); + quoteWrapper = new QuoteWrapper('\''); + } + + @Override + public String dialectName() { + return DialectName.DM.name(); + } + + @Override + public PreparedStatement psForUpsert(final Connection conn, final Entity entity, final String... keys) { + Assert.notEmpty(keys, "Keys must be not empty for DM MERGE SQL."); + SqlBuilder.validateEntity(entity); + final SqlBuilder builder = SqlBuilder.of(quoteWrapper); + final List keyList = Arrays.asList(keys); + + final StringBuilder keyFieldsPart = new StringBuilder(); + final StringBuilder updateFieldsPart = new StringBuilder(); + final StringBuilder insertFieldsPart = new StringBuilder(); + final StringBuilder insertPlaceHolder = new StringBuilder(); + + // 构建字段部分和参数占位符部分 + entity.forEach((field, value) -> { + if (StrUtil.isNotBlank(field) && keyList.contains(field)) { + if (keyFieldsPart.length() > 0) { + keyFieldsPart.append(" and "); + } + keyFieldsPart.append(field).append("= ?"); + builder.addParams(value); + } + }); + + entity.forEach((field, value) -> { + if (StrUtil.isNotBlank(field) && !keyList.contains(field)) { + if (updateFieldsPart.length() > 0) { + // 非第一个参数,追加逗号 + updateFieldsPart.append(", "); + } + updateFieldsPart.append(field).append("= ?"); + builder.addParams(value); + } + }); + + entity.forEach((field, value) -> { + if (StrUtil.isNotBlank(field)) { + if (insertFieldsPart.length() > 0) { + // 非第一个参数,追加逗号 + insertFieldsPart.append(", "); + insertPlaceHolder.append(", "); + } + insertFieldsPart.append((null != quoteWrapper) ? quoteWrapper.wrap(field) : field); + insertPlaceHolder.append("?"); + builder.addParams(value); + } + }); + + String tableName = entity.getTableName(); + if (null != this.quoteWrapper) { + tableName = this.quoteWrapper.wrap(tableName); + } + + builder.append("MERGE INTO ").append(tableName).append(" USING DUAL ON ").append(keyFieldsPart).append(" WHEN MATCHED THEN UPDATE SET ").append(updateFieldsPart).append(" WHEN NOT MATCHED THEN INSERT (").append(insertFieldsPart).append(") VALUES (").append(insertPlaceHolder).append(")"); + + return StatementUtil.prepareStatement(false, dbConfig, conn, builder.build(), builder.getParamValueArray()); + } +} diff --git a/hutool-db/src/test/java/org/dromara/hutool/db/DmTest.java b/hutool-db/src/test/java/org/dromara/hutool/db/DmTest.java new file mode 100644 index 000000000..1a1c2c7da --- /dev/null +++ b/hutool-db/src/test/java/org/dromara/hutool/db/DmTest.java @@ -0,0 +1,37 @@ +package org.dromara.hutool.db; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +/** + * 达梦数据库单元测试 + * + * @author wb04307201 + */ +public class DmTest { + + private static final String DS_GROUP_NAME = "dm"; + + @BeforeAll + @Disabled + public static void init() { + final Db db = Db.of(DS_GROUP_NAME); + db.execute("CREATE TABLE test(a INTEGER, b INTEGER)"); + + db.insert(Entity.of("test").set("a", 1).set("b", 11)); + db.insert(Entity.of("test").set("a", 2).set("b", 21)); + db.insert(Entity.of("test").set("a", 3).set("b", 31)); + db.insert(Entity.of("test").set("a", 4).set("b", 41)); + } + + @Test + @Disabled + public void upsertTest() { + final Db db = Db.of(DS_GROUP_NAME); + db.upsert(Entity.of("test").set("a", 1).set("b", 111), "a"); + final Entity a1 = db.get("test", "a", 1); + Assertions.assertEquals(Long.valueOf(111), a1.getLong("b")); + } +}