mirror of
https://github.com/CarmJos/EasySQL.git
synced 2026-06-04 15:28:20 +08:00
@@ -7,18 +7,22 @@ import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction;
|
|||||||
import cc.carm.lib.easysql.api.builder.*;
|
import cc.carm.lib.easysql.api.builder.*;
|
||||||
import cc.carm.lib.easysql.api.function.SQLDebugHandler;
|
import cc.carm.lib.easysql.api.function.SQLDebugHandler;
|
||||||
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,19 +39,28 @@ public interface SQLManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用于执行 {@link SQLAction#executeAsync()} 的线程池。
|
* 获取用于执行 {@link SQLAction#executeAsync()} 的线程池。
|
||||||
* <br> 默认线程池为 {@link ThreadPoolExecutor} ,大小为 3。
|
* <br> 默认线程池为 {@link #defaultExecutorPool(String)} 。
|
||||||
*
|
*
|
||||||
* @return {@link ExecutorService}
|
* @return {@link ExecutorService}
|
||||||
*/
|
*/
|
||||||
@NotNull ExecutorService getExecutorPool();
|
@NotNull ExecutorService getExecutorPool();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设定用于执行 {@link SQLAction#executeAsync()} 的线程池。
|
* 设定用于执行 {@link SQLAction#executeAsync()} 的线程池.
|
||||||
|
* <br> 默认线程池为 {@link #defaultExecutorPool(String)} 。
|
||||||
*
|
*
|
||||||
* @param executorPool {@link ExecutorService}
|
* @param executorPool {@link ExecutorService}
|
||||||
*/
|
*/
|
||||||
void setExecutorPool(@NotNull ExecutorService executorPool);
|
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 +185,29 @@ public interface SQLManager {
|
|||||||
@Nullable List<Integer> executeSQLBatch(@NotNull Iterable<String> sqlBatch);
|
@Nullable List<Integer> executeSQLBatch(@NotNull Iterable<String> sqlBatch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在库中创建一个表
|
* 获取并操作 {@link DatabaseMetaData} 以得到需要的数据库消息。
|
||||||
|
*
|
||||||
|
* @param metadata 操作与返回的方法
|
||||||
|
* @param <R> 最终结果的返回类型
|
||||||
|
* @return 最终结果,通过 {@link CompletableFuture#get()} 可阻塞并等待结果返回。
|
||||||
|
*/
|
||||||
|
<R> CompletableFuture<R> fetchMetadata(@NotNull SQLFunction<DatabaseMetaData, R> metadata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取并操作 {@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 SQLFunction<DatabaseMetaData, ResultSet> supplier,
|
||||||
|
@NotNull SQLFunction<@NotNull ResultSet, R> reader);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在库中创建一个表。
|
||||||
*
|
*
|
||||||
* @param tableName 表名
|
* @param tableName 表名
|
||||||
* @return {@link TableCreateBuilder}
|
* @return {@link TableCreateBuilder}
|
||||||
@@ -180,7 +215,7 @@ public interface SQLManager {
|
|||||||
TableCreateBuilder createTable(@NotNull String tableName);
|
TableCreateBuilder createTable(@NotNull String tableName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对库中的某个表执行更改
|
* 对库中的某个表执行更改。
|
||||||
*
|
*
|
||||||
* @param tableName 表名
|
* @param tableName 表名
|
||||||
* @return {@link TableAlterBuilder}
|
* @return {@link TableAlterBuilder}
|
||||||
@@ -188,14 +223,23 @@ public interface SQLManager {
|
|||||||
TableAlterBuilder alterTable(@NotNull String tableName);
|
TableAlterBuilder alterTable(@NotNull String tableName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新建一个查询
|
* 快速获取表的部分元数据。
|
||||||
|
* <br> 当需要获取其他元数据时,请使用 {@link #fetchMetadata(SQLFunction, SQLFunction)} 方法。
|
||||||
|
*
|
||||||
|
* @param tablePattern 表名通配符
|
||||||
|
* @return {@link TableMetadataBuilder}
|
||||||
|
*/
|
||||||
|
TableMetadataBuilder fetchTableMetadata(@NotNull String tablePattern);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新建一个查询。
|
||||||
*
|
*
|
||||||
* @return {@link QueryBuilder}
|
* @return {@link QueryBuilder}
|
||||||
*/
|
*/
|
||||||
QueryBuilder createQuery();
|
QueryBuilder createQuery();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建一条插入操作
|
* 创建一条插入操作。
|
||||||
*
|
*
|
||||||
* @param tableName 目标表名
|
* @param tableName 目标表名
|
||||||
* @return {@link InsertBuilder}
|
* @return {@link InsertBuilder}
|
||||||
@@ -203,7 +247,7 @@ public interface SQLManager {
|
|||||||
InsertBuilder<PreparedSQLUpdateAction<Integer>> createInsert(@NotNull String tableName);
|
InsertBuilder<PreparedSQLUpdateAction<Integer>> createInsert(@NotNull String tableName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建支持多组数据的插入操作
|
* 创建支持多组数据的插入操作。
|
||||||
*
|
*
|
||||||
* @param tableName 目标表名
|
* @param tableName 目标表名
|
||||||
* @return {@link InsertBuilder}
|
* @return {@link InsertBuilder}
|
||||||
@@ -211,7 +255,7 @@ public interface SQLManager {
|
|||||||
InsertBuilder<PreparedSQLUpdateBatchAction<Integer>> createInsertBatch(@NotNull String tableName);
|
InsertBuilder<PreparedSQLUpdateBatchAction<Integer>> createInsertBatch(@NotNull String tableName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建一条替换操作
|
* 创建一条替换操作。
|
||||||
*
|
*
|
||||||
* @param tableName 目标表名
|
* @param tableName 目标表名
|
||||||
* @return {@link ReplaceBuilder}
|
* @return {@link ReplaceBuilder}
|
||||||
@@ -219,7 +263,7 @@ public interface SQLManager {
|
|||||||
ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace(@NotNull String tableName);
|
ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace(@NotNull String tableName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建支持多组数据的替换操作
|
* 创建支持多组数据的替换操作。
|
||||||
*
|
*
|
||||||
* @param tableName 目标表名
|
* @param tableName 目标表名
|
||||||
* @return {@link ReplaceBuilder}
|
* @return {@link ReplaceBuilder}
|
||||||
@@ -227,7 +271,7 @@ public interface SQLManager {
|
|||||||
ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch(@NotNull String tableName);
|
ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch(@NotNull String tableName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建更新操作
|
* 创建更新操作。
|
||||||
*
|
*
|
||||||
* @param tableName 目标表名
|
* @param tableName 目标表名
|
||||||
* @return {@link UpdateBuilder}
|
* @return {@link UpdateBuilder}
|
||||||
@@ -235,7 +279,7 @@ public interface SQLManager {
|
|||||||
UpdateBuilder createUpdate(@NotNull String tableName);
|
UpdateBuilder createUpdate(@NotNull String tableName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建删除操作
|
* 创建删除操作。
|
||||||
*
|
*
|
||||||
* @param tableName 目标表名
|
* @param tableName 目标表名
|
||||||
* @return {@link DeleteBuilder}
|
* @return {@link DeleteBuilder}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package cc.carm.lib.easysql.api.builder;
|
||||||
|
|
||||||
|
import cc.carm.lib.easysql.api.SQLBuilder;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public interface TableMetadataBuilder extends SQLBuilder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 本表是否存在
|
||||||
|
*/
|
||||||
|
CompletableFuture<Boolean> validateExist();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param columnName 需要判断的列名
|
||||||
|
* @return 对应列是否存在
|
||||||
|
*/
|
||||||
|
CompletableFuture<Boolean> isColumnExists(String columnName);
|
||||||
|
|
||||||
|
// More coming soon.
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package cc.carm.lib.easysql.builder.impl;
|
||||||
|
|
||||||
|
import cc.carm.lib.easysql.api.builder.TableMetadataBuilder;
|
||||||
|
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 java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
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) -> meta.getTables(null, null, tablePattern, new String[]{"TABLE"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Boolean> isColumnExists(String columnPattern) {
|
||||||
|
return validate((meta) -> meta.getColumns(null, null, tablePattern, columnPattern));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fast validate EXISTS.
|
||||||
|
*
|
||||||
|
* @param supplier supplier to get result set
|
||||||
|
* @return result future
|
||||||
|
*/
|
||||||
|
private CompletableFuture<Boolean> validate(SQLFunction<DatabaseMetaData, ResultSet> supplier) {
|
||||||
|
return getManager().fetchMetadata(supplier, ResultSet::next);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction;
|
|||||||
import cc.carm.lib.easysql.api.builder.*;
|
import cc.carm.lib.easysql.api.builder.*;
|
||||||
import cc.carm.lib.easysql.api.function.SQLDebugHandler;
|
import cc.carm.lib.easysql.api.function.SQLDebugHandler;
|
||||||
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
|
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
|
||||||
|
import cc.carm.lib.easysql.api.function.SQLFunction;
|
||||||
import cc.carm.lib.easysql.builder.impl.*;
|
import cc.carm.lib.easysql.builder.impl.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -20,11 +21,13 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class SQLManagerImpl implements SQLManager {
|
public class SQLManagerImpl implements SQLManager {
|
||||||
@@ -50,12 +53,7 @@ public class SQLManagerImpl implements SQLManager {
|
|||||||
String managerName = "SQLManager" + (name != null ? "#" + name : "");
|
String managerName = "SQLManager" + (name != null ? "#" + name : "");
|
||||||
this.LOGGER = logger;
|
this.LOGGER = logger;
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
this.executorPool = Executors.newFixedThreadPool(3, r -> {
|
this.executorPool = SQLManager.defaultExecutorPool(managerName);
|
||||||
Thread thread = new Thread(r, managerName);
|
|
||||||
thread.setDaemon(true);
|
|
||||||
return thread;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.exceptionHandler = SQLExceptionHandler.detailed(getLogger());
|
this.exceptionHandler = SQLExceptionHandler.detailed(getLogger());
|
||||||
this.debugHandler = SQLDebugHandler.defaultHandler(getLogger());
|
this.debugHandler = SQLDebugHandler.defaultHandler(getLogger());
|
||||||
}
|
}
|
||||||
@@ -80,10 +78,6 @@ public class SQLManagerImpl implements SQLManager {
|
|||||||
this.debugHandler = debugHandler;
|
this.debugHandler = debugHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void debug(String msg) {
|
|
||||||
if (isDebugMode()) getLogger().info("[DEBUG] " + msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Logger getLogger() {
|
public Logger getLogger() {
|
||||||
return LOGGER;
|
return LOGGER;
|
||||||
@@ -160,6 +154,33 @@ public class SQLManagerImpl implements SQLManager {
|
|||||||
return action.execute(null);
|
return action.execute(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> CompletableFuture<R> fetchMetadata(@NotNull SQLFunction<DatabaseMetaData, R> metadata) {
|
||||||
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
|
try (Connection conn = getConnection()) {
|
||||||
|
return metadata.apply(conn.getMetaData());
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}, this.executorPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> CompletableFuture<R> fetchMetadata(@NotNull SQLFunction<DatabaseMetaData, ResultSet> supplier,
|
||||||
|
@NotNull SQLFunction<@NotNull ResultSet, R> reader) {
|
||||||
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
|
try (
|
||||||
|
Connection conn = getConnection();
|
||||||
|
ResultSet rs = supplier.apply(conn.getMetaData())
|
||||||
|
) {
|
||||||
|
if (rs == null) throw new NullPointerException("Metadata返回的ResultSet为null。");
|
||||||
|
else return reader.apply(rs);
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}, this.executorPool);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableCreateBuilder createTable(@NotNull String tableName) {
|
public TableCreateBuilder createTable(@NotNull String tableName) {
|
||||||
return new TableCreateBuilderImpl(this, tableName);
|
return new TableCreateBuilderImpl(this, tableName);
|
||||||
@@ -170,6 +191,11 @@ public class SQLManagerImpl implements SQLManager {
|
|||||||
return new TableAlterBuilderImpl(this, tableName);
|
return new TableAlterBuilderImpl(this, tableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableMetadataBuilder fetchTableMetadata(@NotNull String tablePattern) {
|
||||||
|
return new TableMetadataBuilderImpl(this, tablePattern);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QueryBuilder createQuery() {
|
public QueryBuilder createQuery() {
|
||||||
return new QueryBuilderImpl(this);
|
return new QueryBuilderImpl(this);
|
||||||
|
|||||||
Reference in New Issue
Block a user