mirror of
https://github.com/CarmJos/EasySQL.git
synced 2026-06-05 09:01:26 +08:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f15897eb4 | |||
| 4b4215fb5d | |||
| d206a31986 | |||
| 948dbd3b32 | |||
| 499cf3b322 | |||
| 84c9ce77fa | |||
| 1f515b51b2 | |||
| 54ee3fd4a6 | |||
| 32d8fe8ef0 | |||
| c22be7c324 | |||
| 6bb619374f | |||
| a9a7543e65 | |||
| bb3aaafdd3 | |||
| 0167470fc3 | |||
| 274b54b8d3 | |||
| fc0a3e9754 | |||
| 5e41e21385 | |||
| 0230c77bb2 | |||
| 10ed084ad9 | |||
| 104d4b5476 | |||
| a36554391e | |||
| d92a752239 | |||
| ce088a72a7 | |||
| 26ab19ec75 | |||
| 198a800196 | |||
| 2ea8f3cfa7 | |||
| 2061dc13bf | |||
| 760235fae8 | |||
| d3036ffe4d |
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easysql-parent</artifactId>
|
||||
<version>0.4.2</version>
|
||||
<version>0.4.7</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -206,6 +208,22 @@ public interface SQLAction<T> {
|
||||
void executeAsync(@Nullable SQLHandler<T> success,
|
||||
@Nullable SQLExceptionHandler failure);
|
||||
|
||||
/**
|
||||
* 以异步Future方式执行SQL语句。
|
||||
*
|
||||
* @return 异步执行的Future实例,可通过 {@link Future#get()} 阻塞并等待结果。
|
||||
*/
|
||||
default @NotNull CompletableFuture<Void> executeFuture() {
|
||||
return executeFuture((t -> null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 以异步Future方式执行SQL语句。
|
||||
*
|
||||
* @return 异步执行的Future实例,可通过 {@link Future#get()} 阻塞并等待结果。
|
||||
*/
|
||||
<R> @NotNull CompletableFuture<R> executeFuture(@NotNull SQLFunction<T, R> handler);
|
||||
|
||||
default void handleException(@Nullable SQLExceptionHandler handler, SQLException exception) {
|
||||
if (handler == null) handler = defaultExceptionHandler();
|
||||
handler.accept(exception, this);
|
||||
|
||||
@@ -5,20 +5,25 @@ import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
|
||||
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
|
||||
import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction;
|
||||
import cc.carm.lib.easysql.api.builder.*;
|
||||
import cc.carm.lib.easysql.api.function.SQLBiFunction;
|
||||
import cc.carm.lib.easysql.api.function.SQLDebugHandler;
|
||||
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
|
||||
import cc.carm.lib.easysql.api.function.SQLFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
@@ -35,19 +40,28 @@ public interface SQLManager {
|
||||
|
||||
/**
|
||||
* 获取用于执行 {@link SQLAction#executeAsync()} 的线程池。
|
||||
* <br> 默认线程池为 {@link ThreadPoolExecutor} ,大小为 3。
|
||||
* <br> 默认线程池为 {@link #defaultExecutorPool(String)} 。
|
||||
*
|
||||
* @return {@link ExecutorService}
|
||||
*/
|
||||
@NotNull ExecutorService getExecutorPool();
|
||||
|
||||
/**
|
||||
* 设定用于执行 {@link SQLAction#executeAsync()} 的线程池。
|
||||
* 设定用于执行 {@link SQLAction#executeAsync()} 的线程池.
|
||||
* <br> 默认线程池为 {@link #defaultExecutorPool(String)} 。
|
||||
*
|
||||
* @param executorPool {@link ExecutorService}
|
||||
*/
|
||||
void setExecutorPool(@NotNull ExecutorService executorPool);
|
||||
|
||||
static ExecutorService defaultExecutorPool(String threadName) {
|
||||
return Executors.newFixedThreadPool(4, r -> {
|
||||
Thread thread = new Thread(r, threadName);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设定是否启用调试模式。
|
||||
@@ -172,7 +186,55 @@ public interface SQLManager {
|
||||
@Nullable List<Integer> executeSQLBatch(@NotNull Iterable<String> sqlBatch);
|
||||
|
||||
/**
|
||||
* 在库中创建一个表
|
||||
* 获取并操作 {@link DatabaseMetaData} 以得到需要的数据库消息。
|
||||
*
|
||||
* @param reader 操作与读取的方法
|
||||
* @param <R> 最终结果的返回类型
|
||||
* @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。
|
||||
*/
|
||||
default <R> CompletableFuture<R> fetchMetadata(@NotNull SQLFunction<DatabaseMetaData, R> reader) {
|
||||
return fetchMetadata((meta, conn) -> reader.apply(meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取并操作 {@link DatabaseMetaData} 提供的指定 {@link ResultSet} 以得到需要的数据库消息。
|
||||
* <br> 该方法会自动关闭 {@link ResultSet} 。
|
||||
*
|
||||
* @param supplier 操作 {@link DatabaseMetaData} 以提供信息所在的 {@link ResultSet}
|
||||
* @param reader 读取 {@link ResultSet} 中指定信息的方法
|
||||
* @param <R> 最终结果的返回类型
|
||||
* @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。
|
||||
* @throws NullPointerException 当 supplier 提供的 {@link ResultSet} 为NULL时抛出
|
||||
*/
|
||||
default <R> CompletableFuture<R> fetchMetadata(@NotNull SQLFunction<DatabaseMetaData, ResultSet> supplier,
|
||||
@NotNull SQLFunction<@NotNull ResultSet, R> reader) {
|
||||
return fetchMetadata((meta, conn) -> supplier.apply(meta), reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取并操作 {@link DatabaseMetaData} 以得到需要的数据库消息。
|
||||
*
|
||||
* @param reader 操作与读取的方法
|
||||
* @param <R> 最终结果的返回类型
|
||||
* @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。
|
||||
*/
|
||||
<R> CompletableFuture<R> fetchMetadata(@NotNull SQLBiFunction<DatabaseMetaData, Connection, R> reader);
|
||||
|
||||
/**
|
||||
* 获取并操作 {@link DatabaseMetaData} 提供的指定 {@link ResultSet} 以得到需要的数据库消息。
|
||||
* <br> 该方法会自动关闭 {@link ResultSet} 。
|
||||
*
|
||||
* @param supplier 操作 {@link DatabaseMetaData} 以提供信息所在的 {@link ResultSet}
|
||||
* @param reader 读取 {@link ResultSet} 中指定信息的方法
|
||||
* @param <R> 最终结果的返回类型
|
||||
* @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。
|
||||
* @throws NullPointerException 当 supplier 提供的 {@link ResultSet} 为NULL时抛出
|
||||
*/
|
||||
<R> CompletableFuture<R> fetchMetadata(@NotNull SQLBiFunction<DatabaseMetaData, Connection, ResultSet> supplier,
|
||||
@NotNull SQLFunction<@NotNull ResultSet, R> reader);
|
||||
|
||||
/**
|
||||
* 在库中创建一个表。
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return {@link TableCreateBuilder}
|
||||
@@ -180,7 +242,7 @@ public interface SQLManager {
|
||||
TableCreateBuilder createTable(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 对库中的某个表执行更改
|
||||
* 对库中的某个表执行更改。
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return {@link TableAlterBuilder}
|
||||
@@ -188,14 +250,23 @@ public interface SQLManager {
|
||||
TableAlterBuilder alterTable(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 新建一个查询
|
||||
* 快速获取表的部分元数据。
|
||||
* <br> 当需要获取其他元数据时,请使用 {@link #fetchMetadata(SQLFunction, SQLFunction)} 方法。
|
||||
*
|
||||
* @param tablePattern 表名通配符
|
||||
* @return {@link TableMetadataBuilder}
|
||||
*/
|
||||
TableMetadataBuilder fetchTableMetadata(@NotNull String tablePattern);
|
||||
|
||||
/**
|
||||
* 新建一个查询。
|
||||
*
|
||||
* @return {@link QueryBuilder}
|
||||
*/
|
||||
QueryBuilder createQuery();
|
||||
|
||||
/**
|
||||
* 创建一条插入操作
|
||||
* 创建一条插入操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link InsertBuilder}
|
||||
@@ -203,7 +274,7 @@ public interface SQLManager {
|
||||
InsertBuilder<PreparedSQLUpdateAction<Integer>> createInsert(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 创建支持多组数据的插入操作
|
||||
* 创建支持多组数据的插入操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link InsertBuilder}
|
||||
@@ -211,7 +282,7 @@ public interface SQLManager {
|
||||
InsertBuilder<PreparedSQLUpdateBatchAction<Integer>> createInsertBatch(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 创建一条替换操作
|
||||
* 创建一条替换操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link ReplaceBuilder}
|
||||
@@ -219,7 +290,7 @@ public interface SQLManager {
|
||||
ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 创建支持多组数据的替换操作
|
||||
* 创建支持多组数据的替换操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link ReplaceBuilder}
|
||||
@@ -227,7 +298,7 @@ public interface SQLManager {
|
||||
ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 创建更新操作
|
||||
* 创建更新操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link UpdateBuilder}
|
||||
@@ -235,7 +306,7 @@ public interface SQLManager {
|
||||
UpdateBuilder createUpdate(@NotNull String tableName);
|
||||
|
||||
/**
|
||||
* 创建删除操作
|
||||
* 创建删除操作。
|
||||
*
|
||||
* @param tableName 目标表名
|
||||
* @return {@link DeleteBuilder}
|
||||
|
||||
@@ -5,6 +5,7 @@ import cc.carm.lib.easysql.api.action.query.QueryAction;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -50,6 +51,10 @@ public interface SQLQuery extends AutoCloseable {
|
||||
|
||||
ResultSet getResultSet();
|
||||
|
||||
default boolean containsResult(String columnName) throws SQLException {
|
||||
return getResultSet() != null && getResultSet().getObject(columnName) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到设定的SQL语句
|
||||
*
|
||||
|
||||
@@ -125,8 +125,7 @@ public interface SQLTable {
|
||||
}
|
||||
|
||||
default @NotNull ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace(@NotNull SQLManager sqlManager) {
|
||||
return Optional.ofNullable(getSQLManager()).map(this::createReplace)
|
||||
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
|
||||
return sqlManager.createReplace(getTableName());
|
||||
}
|
||||
|
||||
default @NotNull ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch() {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package cc.carm.lib.easysql.api.builder;
|
||||
|
||||
import cc.carm.lib.easysql.api.SQLBuilder;
|
||||
import cc.carm.lib.easysql.api.function.SQLFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface TableMetadataBuilder extends SQLBuilder {
|
||||
|
||||
/**
|
||||
* @return 本表是否存在
|
||||
*/
|
||||
CompletableFuture<Boolean> validateExist();
|
||||
|
||||
/**
|
||||
* 对表内的数据列元数据进行读取
|
||||
*
|
||||
* @param columnPattern 列的名称匹配表达式, 为空则匹配所有列
|
||||
* @param reader 读取的方法
|
||||
* @param <R> 结果类型
|
||||
* @return 读取结果
|
||||
*/
|
||||
<R> CompletableFuture<R> fetchColumns(@Nullable String columnPattern,
|
||||
@NotNull SQLFunction<ResultSet, R> reader);
|
||||
|
||||
/**
|
||||
* @param columnPattern 需要判断的列名表达式
|
||||
* @return 对应列是否存在
|
||||
*/
|
||||
CompletableFuture<Boolean> isColumnExists(@NotNull String columnPattern);
|
||||
|
||||
/**
|
||||
* 列出所有表内的全部列。
|
||||
*
|
||||
* @return 表内全部数据列的列名
|
||||
*/
|
||||
default CompletableFuture<@Unmodifiable Set<String>> listColumns() {
|
||||
return listColumns(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出所有满足表达式的列。
|
||||
*
|
||||
* @param columnPattern 列名表达式,为空则列出全部
|
||||
* @return 所有满足表达式的列名
|
||||
*/
|
||||
CompletableFuture<@Unmodifiable Set<String>> listColumns(@Nullable String columnPattern);
|
||||
|
||||
// More coming soon.
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cc.carm.lib.easysql.api.function;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SQLBiFunction<T, U, R> {
|
||||
|
||||
@Nullable
|
||||
R apply(@NotNull T t, @NotNull U u) throws SQLException;
|
||||
|
||||
default <V> SQLBiFunction<T, U, V> then(@NotNull SQLFunction<? super R, ? extends V> after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (T t, U u) -> {
|
||||
R r = apply(t, u);
|
||||
if (r == null) return null;
|
||||
else return after.apply(r);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easysql-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>0.4.2</version>
|
||||
<version>0.4.7</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<maven.javadoc.skip>true</maven.javadoc.skip>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
|
||||
<log4j.version>2.17.2</log4j.version>
|
||||
<log4j.version>2.20.0</log4j.version>
|
||||
</properties>
|
||||
|
||||
<artifactId>easysql-demo</artifactId>
|
||||
|
||||
@@ -8,9 +8,11 @@ import cc.carm.lib.easysql.api.util.TimeDateUtils;
|
||||
import cc.carm.lib.easysql.api.util.UUIDUtil;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@TestOnly
|
||||
@SuppressWarnings("all")
|
||||
@@ -157,4 +159,22 @@ public class EasySQLDemo {
|
||||
}
|
||||
}
|
||||
|
||||
public void metadata(SQLManager sql) {
|
||||
|
||||
// 操作数据库元数据,直接返回结果。
|
||||
CompletableFuture<Boolean> roFuture = sql.fetchMetadata(DatabaseMetaData::isReadOnly);
|
||||
CompletableFuture<Integer> maxColumnFuture = sql.fetchMetadata(DatabaseMetaData::getMaxColumnsInSelect);
|
||||
|
||||
// 操作有 ResultSet 元数据。该方法会自动关闭ResultSet。
|
||||
CompletableFuture<Boolean> tableExists = sql.fetchMetadata(
|
||||
meta -> meta.getTables(null, null, "表名", new String[]{"TABKE"}),
|
||||
resultSet -> resultSet.next()
|
||||
);
|
||||
|
||||
// SQLManager附带了几个常用元数据的获取方法。
|
||||
CompletableFuture<Boolean> tableExists2 = sql.fetchTableMetadata("表名").validateExist();
|
||||
CompletableFuture<Boolean> columnExists = sql.fetchTableMetadata("表名").isColumnExists("字段名");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,7 +50,10 @@ public class EasySQLTest {
|
||||
tests.add(new SQLUpdateReturnKeysTest());
|
||||
tests.add(new QueryCloseTest());
|
||||
tests.add(new QueryFunctionTest());
|
||||
tests.add(new QueryFutureTest());
|
||||
tests.add(new QueryAsyncTest());
|
||||
|
||||
tests.add(new TableMetadataTest());
|
||||
// tests.add(new DeleteTest());
|
||||
|
||||
print("准备进行测试...");
|
||||
|
||||
@@ -4,8 +4,6 @@ import cc.carm.lib.easysql.api.SQLManager;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
public abstract class TestHandler {
|
||||
|
||||
protected static void print(@NotNull String format, Object... params) {
|
||||
@@ -13,7 +11,7 @@ public abstract class TestHandler {
|
||||
}
|
||||
|
||||
@ApiStatus.OverrideOnly
|
||||
public abstract void onTest(SQLManager sqlManager) throws SQLException;
|
||||
public abstract void onTest(SQLManager sqlManager) throws Exception;
|
||||
|
||||
public boolean executeTest(int index, SQLManager sqlManager) {
|
||||
String testName = getClass().getSimpleName();
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package cc.carm.lib.easysql.tests;
|
||||
|
||||
import cc.carm.lib.easysql.TestHandler;
|
||||
import cc.carm.lib.easysql.api.SQLManager;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class QueryFutureTest extends TestHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public void onTest(SQLManager sqlManager) throws SQLException, ExecutionException, InterruptedException {
|
||||
|
||||
|
||||
Future<Integer> future = sqlManager.createQuery()
|
||||
.inTable("test_user_table")
|
||||
.orderBy("id", false)
|
||||
.setLimit(1)
|
||||
.build().executeFuture((query) -> {
|
||||
if (!query.getResultSet().next()) {
|
||||
return -1;
|
||||
} else {
|
||||
return query.getResultSet().getInt("id");
|
||||
}
|
||||
});
|
||||
|
||||
int id = future.get();
|
||||
System.out.println("id(future): " + id);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cc.carm.lib.easysql.tests;
|
||||
|
||||
import cc.carm.lib.easysql.TestHandler;
|
||||
import cc.carm.lib.easysql.api.SQLManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class TableMetadataTest extends TestHandler {
|
||||
|
||||
@Override
|
||||
public void onTest(SQLManager sqlManager) throws Exception {
|
||||
|
||||
print(" 获取数据库中所有的表");
|
||||
CompletableFuture<List<String>> tables = sqlManager.fetchMetadata(
|
||||
(meta) -> meta.getTables(null, null, "%", new String[]{"TABLE"}),
|
||||
(rs) -> {
|
||||
List<String> data = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
data.add(rs.getString("TABLE_NAME"));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
);
|
||||
print("表名:" + Arrays.toString(tables.get().toArray()));
|
||||
|
||||
print(" 获取数据库中所有的列");
|
||||
CompletableFuture<Set<String>> columns = sqlManager.fetchTableMetadata("test%").listColumns();
|
||||
print("列名:" + Arrays.toString(columns.get().toArray()));
|
||||
|
||||
print("表是否存在 " + sqlManager.fetchTableMetadata("test_user_info").validateExist().get());
|
||||
print("列是否存在 " + sqlManager.fetchTableMetadata("test_user_info").isColumnExists("uid").get());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easysql-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>0.4.2</version>
|
||||
<version>0.4.7</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package cc.carm.lib.easysql.action;
|
||||
|
||||
import cc.carm.lib.easysql.api.SQLAction;
|
||||
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
|
||||
import cc.carm.lib.easysql.api.function.SQLFunction;
|
||||
import cc.carm.lib.easysql.api.function.SQLHandler;
|
||||
import cc.carm.lib.easysql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -10,6 +11,7 @@ import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class AbstractSQLAction<T> implements SQLAction<T> {
|
||||
@@ -91,4 +93,10 @@ public abstract class AbstractSQLAction<T> implements SQLAction<T> {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull <R> CompletableFuture<R> executeFuture(@NotNull SQLFunction<T, R> handler) {
|
||||
CompletableFuture<R> future = new CompletableFuture<>();
|
||||
executeAsync((t -> future.complete(handler.apply(t))), (e, q) -> future.completeExceptionally(e));
|
||||
return future;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package cc.carm.lib.easysql.builder.impl;
|
||||
|
||||
import cc.carm.lib.easysql.api.builder.TableMetadataBuilder;
|
||||
import cc.carm.lib.easysql.api.function.SQLBiFunction;
|
||||
import cc.carm.lib.easysql.api.function.SQLFunction;
|
||||
import cc.carm.lib.easysql.builder.AbstractSQLBuilder;
|
||||
import cc.carm.lib.easysql.manager.SQLManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class TableMetadataBuilderImpl
|
||||
extends AbstractSQLBuilder
|
||||
implements TableMetadataBuilder {
|
||||
|
||||
protected final @NotNull String tablePattern;
|
||||
|
||||
public TableMetadataBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tablePattern) {
|
||||
super(manager);
|
||||
this.tablePattern = tablePattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> validateExist() {
|
||||
return validate((meta, conn) -> meta.getTables(conn.getCatalog(), conn.getSchema(), tablePattern.toUpperCase(), new String[]{"TABLE"}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> CompletableFuture<R> fetchColumns(@Nullable String columnPattern,
|
||||
@NotNull SQLFunction<ResultSet, R> reader) {
|
||||
return getManager().fetchMetadata((meta, conn) -> meta.getColumns(
|
||||
conn.getCatalog(), conn.getSchema(), tablePattern.toUpperCase(),
|
||||
Optional.ofNullable(columnPattern).map(String::toUpperCase).orElse("%")
|
||||
), reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> isColumnExists(@NotNull String columnPattern) {
|
||||
return validate((meta, conn) -> meta.getColumns(
|
||||
conn.getCatalog(), conn.getSchema(),
|
||||
tablePattern.toUpperCase(), columnPattern.toUpperCase()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Set<String>> listColumns(@Nullable String columnPattern) {
|
||||
return fetchColumns(columnPattern, (rs) -> {
|
||||
Set<String> data = new LinkedHashSet<>();
|
||||
while (rs.next()) {
|
||||
data.add(rs.getString("COLUMN_NAME"));
|
||||
}
|
||||
return Collections.unmodifiableSet(data);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* fast validate EXISTS.
|
||||
*
|
||||
* @param supplier supplier to get result set
|
||||
* @return result future
|
||||
*/
|
||||
private CompletableFuture<Boolean> validate(SQLBiFunction<DatabaseMetaData, Connection, ResultSet> supplier) {
|
||||
return getManager().fetchMetadata(supplier, ResultSet::next);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,8 +10,10 @@ import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
|
||||
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
|
||||
import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction;
|
||||
import cc.carm.lib.easysql.api.builder.*;
|
||||
import cc.carm.lib.easysql.api.function.SQLBiFunction;
|
||||
import cc.carm.lib.easysql.api.function.SQLDebugHandler;
|
||||
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
|
||||
import cc.carm.lib.easysql.api.function.SQLFunction;
|
||||
import cc.carm.lib.easysql.builder.impl.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -20,11 +22,13 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SQLManagerImpl implements SQLManager {
|
||||
@@ -50,12 +54,7 @@ public class SQLManagerImpl implements SQLManager {
|
||||
String managerName = "SQLManager" + (name != null ? "#" + name : "");
|
||||
this.LOGGER = logger;
|
||||
this.dataSource = dataSource;
|
||||
this.executorPool = Executors.newFixedThreadPool(3, r -> {
|
||||
Thread thread = new Thread(r, managerName);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
|
||||
this.executorPool = SQLManager.defaultExecutorPool(managerName);
|
||||
this.exceptionHandler = SQLExceptionHandler.detailed(getLogger());
|
||||
this.debugHandler = SQLDebugHandler.defaultHandler(getLogger());
|
||||
}
|
||||
@@ -80,10 +79,6 @@ public class SQLManagerImpl implements SQLManager {
|
||||
this.debugHandler = debugHandler;
|
||||
}
|
||||
|
||||
public void debug(String msg) {
|
||||
if (isDebugMode()) getLogger().info("[DEBUG] " + msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return LOGGER;
|
||||
@@ -160,6 +155,30 @@ public class SQLManagerImpl implements SQLManager {
|
||||
return action.execute(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> CompletableFuture<R> fetchMetadata(@NotNull SQLBiFunction<DatabaseMetaData, Connection, R> reader) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try (Connection conn = getConnection()) {
|
||||
return reader.apply(conn.getMetaData(), conn);
|
||||
} catch (SQLException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}, this.executorPool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> CompletableFuture<R> fetchMetadata(@NotNull SQLBiFunction<DatabaseMetaData, Connection, ResultSet> supplier,
|
||||
@NotNull SQLFunction<@NotNull ResultSet, R> reader) {
|
||||
return fetchMetadata((meta, conn) -> {
|
||||
try (ResultSet rs = supplier.apply(conn.getMetaData(), conn)) {
|
||||
if (rs == null) throw new NullPointerException("Metadata返回的ResultSet为null。");
|
||||
else return reader.apply(rs);
|
||||
} catch (SQLException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCreateBuilder createTable(@NotNull String tableName) {
|
||||
return new TableCreateBuilderImpl(this, tableName);
|
||||
@@ -170,6 +189,11 @@ public class SQLManagerImpl implements SQLManager {
|
||||
return new TableAlterBuilderImpl(this, tableName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableMetadataBuilder fetchTableMetadata(@NotNull String tablePattern) {
|
||||
return new TableMetadataBuilderImpl(this, tablePattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryBuilder createQuery() {
|
||||
return new QueryBuilderImpl(this);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easysql-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>0.4.2</version>
|
||||
<version>0.4.7</version>
|
||||
|
||||
<modules>
|
||||
<module>api</module>
|
||||
@@ -116,7 +116,7 @@
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>23.0.0</version>
|
||||
<version>24.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<classifier>javadoc</classifier>
|
||||
<detectJavaApiLink>false</detectJavaApiLink>
|
||||
@@ -196,7 +196,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>${jdk.version}</source>
|
||||
<target>${jdk.version}</target>
|
||||
@@ -208,7 +208,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.2.2</version>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
@@ -228,7 +228,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
@@ -256,7 +256,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
</configuration>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easysql-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>0.4.2</version>
|
||||
<version>0.4.7</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -79,7 +79,7 @@
|
||||
<!--项目地址 https://github.com/Chris2018998/BeeCP -->
|
||||
<groupId>com.github.chris2018998</groupId>
|
||||
<artifactId>beecp</artifactId>
|
||||
<version>3.3.6</version>
|
||||
<version>3.4.0</version>
|
||||
<optional>true</optional>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
@@ -107,7 +107,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easysql-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>0.4.2</version>
|
||||
<version>0.4.7</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -102,7 +102,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
||||
Reference in New Issue
Block a user