mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add hana
This commit is contained in:
parent
581a5dd0fd
commit
58d44d6086
@ -164,5 +164,11 @@
|
||||
<version>2.4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sap.cloud.db.jdbc</groupId>
|
||||
<artifactId>ngdbc</artifactId>
|
||||
<version>2.24.7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -89,6 +89,9 @@ public class DialectFactory {
|
||||
} else if (DriverNames.DRIVER_GOLDENDB.equalsIgnoreCase(driverName)) {
|
||||
// MySQL兼容
|
||||
return new MysqlDialect(dbConfig);
|
||||
} else if (DriverNames.DRIVER_HANA.equalsIgnoreCase(driverName)) {
|
||||
// SAP HANA
|
||||
return new HanaDialect(dbConfig);
|
||||
}
|
||||
}
|
||||
// 无法识别可支持的数据库类型默认使用ANSI方言,可兼容大部分SQL语句
|
||||
|
@ -25,7 +25,7 @@ import org.dromara.hutool.core.text.StrUtil;
|
||||
* @author Looly
|
||||
*/
|
||||
public enum DialectName {
|
||||
ANSI, MYSQL, ORACLE, POSTGRESQL, SQLITE3, H2, SQLSERVER, SQLSERVER2012, PHOENIX, DM;
|
||||
ANSI, MYSQL, ORACLE, POSTGRESQL, SQLITE3, H2, SQLSERVER, SQLSERVER2012, PHOENIX, DM, HANA;
|
||||
|
||||
/**
|
||||
* 是否为指定数据库方言,检查时不分区大小写
|
||||
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Hutool Team and hutool.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.db.dialect.impl;
|
||||
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.db.DbException;
|
||||
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.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Hana数据库方言
|
||||
*
|
||||
* @author daoyou.dev
|
||||
*/
|
||||
public class HanaDialect extends AnsiSqlDialect {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param config 数据库配置对象
|
||||
*/
|
||||
public HanaDialect(final DbConfig config) {
|
||||
super(config);
|
||||
quoteWrapper = new QuoteWrapper('"');
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dialectName() {
|
||||
return DialectName.HANA.name();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建用于upsert的{@link PreparedStatement}。
|
||||
* SAP HANA 使用 MERGE INTO 语法来实现 UPSERT 操作。
|
||||
* <p>
|
||||
* 生成 SQL 语法为:
|
||||
* <pre>{@code
|
||||
* MERGE INTO demo AS target
|
||||
* USING (SELECT ? AS a, ? AS b, ? AS c FROM DUMMY) AS source
|
||||
* ON target.id = source.id
|
||||
* WHEN MATCHED THEN
|
||||
* UPDATE SET target.a = source.a, target.b = source.b, target.c = source.c
|
||||
* WHEN NOT MATCHED THEN
|
||||
* INSERT (a, b, c) VALUES (source.a, source.b, source.c);
|
||||
* }</pre>
|
||||
*
|
||||
* @param conn 数据库连接对象
|
||||
* @param entity 数据实体类(包含表名)
|
||||
* @param keys 主键字段数组,通常用于确定匹配条件(联合主键)
|
||||
* @return PreparedStatement
|
||||
* @throws DbException SQL 执行异常
|
||||
*/
|
||||
@Override
|
||||
public PreparedStatement psForUpsert(final Connection conn, final Entity entity, final String... keys) throws DbException {
|
||||
SqlBuilder.validateEntity(entity);
|
||||
final SqlBuilder builder = SqlBuilder.of(quoteWrapper);
|
||||
|
||||
final List<String> columns = new ArrayList<>();
|
||||
|
||||
// 构建字段部分和参数占位符部分
|
||||
entity.forEach((field, value) -> {
|
||||
if (StrUtil.isNotBlank(field)) {
|
||||
columns.add(quoteWrapper != null ? quoteWrapper.wrap(field) : field);
|
||||
builder.addParams(value);
|
||||
}
|
||||
});
|
||||
|
||||
String tableName = entity.getTableName();
|
||||
if (quoteWrapper != null) {
|
||||
tableName = quoteWrapper.wrap(tableName);
|
||||
}
|
||||
|
||||
// 构建 UPSERT 语句
|
||||
builder.append("UPSERT ").append(tableName).append(" (");
|
||||
builder.append(String.join(", ", columns));
|
||||
builder.append(") VALUES (");
|
||||
builder.append(String.join(", ", Collections.nCopies(columns.size(), "?")));
|
||||
builder.append(") WITH PRIMARY KEY");
|
||||
|
||||
return StatementUtil.prepareStatement(false, this.dbConfig, conn, builder.build(), builder.getParamValueArray());
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ import java.util.List;
|
||||
* @author Looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class DriverIdentifier implements DriverNames{
|
||||
public class DriverIdentifier implements DriverNames {
|
||||
|
||||
/**
|
||||
* 单例驱动识别器
|
||||
@ -131,7 +131,9 @@ public class DriverIdentifier implements DriverNames{
|
||||
new StartsWithDriverMatcher(DRIVER_GAUSS, "jdbc:zenith:"),
|
||||
new StartsWithDriverMatcher(DRIVER_OPENGAUSS, "jdbc:opengauss:"),
|
||||
// 中兴GoldenDB
|
||||
new StartsWithDriverMatcher(DRIVER_GOLDENDB, "jdbc:goldendb:")
|
||||
new StartsWithDriverMatcher(DRIVER_GOLDENDB, "jdbc:goldendb:"),
|
||||
// SAP HANA
|
||||
new StartsWithDriverMatcher(DRIVER_HANA, "jdbc:sap:")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -252,9 +252,12 @@ public interface DriverNames {
|
||||
* JDBC 驱动 Greenplum
|
||||
*/
|
||||
String DRIVER_GREENPLUM = "com.pivotal.jdbc.GreenplumDriver";
|
||||
|
||||
/**
|
||||
* JDBC 驱动 GoldenDB
|
||||
*/
|
||||
String DRIVER_GOLDENDB = "com.goldendb.jdbc.Driver";
|
||||
/**
|
||||
* JDBC 驱动 Sap Hana
|
||||
*/
|
||||
String DRIVER_HANA = "com.sap.db.jdbc.Driver";
|
||||
}
|
||||
|
82
hutool-db/src/test/java/org/dromara/hutool/db/HanaTest.java
Normal file
82
hutool-db/src/test/java/org/dromara/hutool/db/HanaTest.java
Normal file
@ -0,0 +1,82 @@
|
||||
package org.dromara.hutool.db;
|
||||
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class HanaTest {
|
||||
@BeforeAll
|
||||
public static void createTable() {
|
||||
final Db db = Db.of("hana");
|
||||
final long count = db.count("SELECT * FROM SYS.TABLES WHERE TABLE_NAME = ? AND SCHEMA_NAME = CURRENT_SCHEMA", "user");
|
||||
if (count > 0) {
|
||||
db.execute("drop table \"user\"");
|
||||
}
|
||||
db.execute("CREATE COLUMN TABLE \"user\" (\"id\" INT NOT NULL, \"account\" VARCHAR(255), \"name\" VARCHAR(255), \"text\" VARCHAR(255), \"test1\" VARCHAR(255), \"pass\" VARCHAR(255), PRIMARY KEY (\"id\"))");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void insertTest() {
|
||||
for (int id = 100; id < 200; id++) {
|
||||
Db.of("hana").insert(Entity.of("user")//
|
||||
.set("id", id)//
|
||||
.set("name", "测试用户" + id)//
|
||||
.set("text", "描述" + id)//
|
||||
.set("test1", "t" + id)//
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 事务测试<br>
|
||||
* 更新三条信息,低2条后抛出异常,正常情况下三条都应该不变
|
||||
*
|
||||
* @throws SQLException SQL异常
|
||||
*/
|
||||
@Test
|
||||
@Disabled
|
||||
public void txTest() throws SQLException {
|
||||
Db.of("hana").tx(db -> {
|
||||
final int update = db.update(Entity.of("user").set("text", "描述100"), Entity.of().set("id", 100));
|
||||
db.update(Entity.of("user").set("text", "描述101"), Entity.of().set("id", 101));
|
||||
if (1 == update) {
|
||||
// 手动指定异常,然后测试回滚触发
|
||||
throw new RuntimeException("Error");
|
||||
}
|
||||
db.update(Entity.of("user").set("text", "描述102"), Entity.of().set("id", 102));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void pageTest() {
|
||||
final PageResult<Entity> result = Db.of("hana").page(Entity.of("\"user\""), new Page(2, 10));
|
||||
for (final Entity entity : result) {
|
||||
Console.log(entity.get("id"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void getTimeStampTest() {
|
||||
final List<Entity> all = Db.of("hana").findAll("user");
|
||||
Console.log(all);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upsertTest() {
|
||||
final Db db = Db.of("hana");
|
||||
db.insert(Entity.of("user").set("id", 1).set("account", "ice").set("pass", "123456"));
|
||||
db.upsert(Entity.of("user").set("id", 1).set("account", "daoyou").set("pass", "a123456").set("name", "道友"));
|
||||
final Entity user = db.get(Entity.of("user").set("id", 1));
|
||||
System.out.println("user=======" + user.getStr("account") + "___" + user.getStr("pass"));
|
||||
assertEquals("daoyou", user.getStr("account"));
|
||||
}
|
||||
}
|
@ -108,3 +108,9 @@ url = jdbc:oceanbase://localhost:2881/test
|
||||
user = root
|
||||
pass = 123456
|
||||
remarks = true
|
||||
|
||||
[hana]
|
||||
url = jdbc:sap://localhost:30015/HAP_CONN?autoReconnect=true
|
||||
user = DB
|
||||
pass = 123456
|
||||
remarks = true
|
||||
|
Loading…
x
Reference in New Issue
Block a user