1
mirror of https://github.com/CarmJos/EasySQL.git synced 2026-06-05 00:25:32 +08:00

修改文件夹名与项目配置

This commit is contained in:
2022-03-25 00:40:28 +08:00
parent e60c44aaae
commit 0bdfe3d556
72 changed files with 17 additions and 9 deletions
@@ -0,0 +1,86 @@
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.SQLHandler;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.sql.SQLException;
import java.util.Objects;
import java.util.UUID;
public abstract class AbstractSQLAction<T> implements SQLAction<T> {
protected final @NotNull String sqlContent;
private final @NotNull SQLManagerImpl sqlManager;
private final @NotNull UUID uuid;
private final long createTime;
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql) {
this(manager, sql, System.currentTimeMillis());
}
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, @NotNull UUID uuid) {
this(manager, sql, uuid, System.currentTimeMillis());
}
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, long createTime) {
this(manager, sql, UUID.randomUUID(), createTime);
}
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql,
@NotNull UUID uuid, long createTime) {
Objects.requireNonNull(manager);
Objects.requireNonNull(sql);
Objects.requireNonNull(uuid);
this.sqlManager = manager;
this.sqlContent = sql;
this.uuid = uuid;
this.createTime = createTime;
}
@Override
public @NotNull UUID getActionUUID() {
return this.uuid;
}
@Override
public @NotNull String getShortID() {
return getActionUUID().toString().substring(0, 8);
}
@Override
public long getCreateTime() {
return this.createTime;
}
@Override
public @NotNull String getSQLContent() {
return this.sqlContent.trim();
}
@Override
public @NotNull SQLManagerImpl getManager() {
return this.sqlManager;
}
protected void outputDebugMessage() {
getManager().debug("# " + getShortID() + " -> { " + getSQLContent() + " }");
}
@Override
@SuppressWarnings("FutureReturnValueIgnored")
public void executeAsync(SQLHandler<T> success, SQLExceptionHandler failure) {
getManager().getExecutorPool().submit(() -> {
try {
T returnedValue = execute();
if (success != null) success.accept(returnedValue);
} catch (SQLException e) {
handleException(failure, e);
}
});
}
}
@@ -0,0 +1,74 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.util.StatementUtil;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class PreparedSQLBatchUpdateActionImpl
extends AbstractSQLAction<List<Integer>>
implements PreparedSQLUpdateBatchAction {
boolean returnKeys = false;
List<Object[]> allParams;
public PreparedSQLBatchUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
this.allParams = new ArrayList<>();
}
@Override
public PreparedSQLUpdateBatchAction setAllParams(Iterable<Object[]> allParams) {
List<Object[]> paramsList = new ArrayList<>();
allParams.forEach(paramsList::add);
this.allParams = paramsList;
return this;
}
@Override
public PreparedSQLUpdateBatchAction addParamsBatch(Object... params) {
this.allParams.add(params);
return this;
}
@Override
public PreparedSQLUpdateBatchAction setReturnGeneratedKeys(boolean returnGeneratedKey) {
this.returnKeys = returnGeneratedKey;
return this;
}
@Override
public @NotNull List<Integer> execute() throws SQLException {
try (Connection connection = getManager().getConnection()) {
try (PreparedStatement statement = StatementUtil.createPrepareStatementBatch(
connection, getSQLContent(), allParams, returnKeys
)) {
outputDebugMessage();
int[] executed = statement.executeBatch();
if (!returnKeys) return Arrays.stream(executed).boxed().collect(Collectors.toList());
else {
try (ResultSet resultSet = statement.getGeneratedKeys()) {
List<Integer> generatedKeys = new ArrayList<>();
while (resultSet.next()) {
generatedKeys.add(resultSet.getInt(1));
}
return generatedKeys;
}
}
}
}
}
}
@@ -0,0 +1,77 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.util.StatementUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class PreparedSQLUpdateActionImpl
extends SQLUpdateActionImpl
implements PreparedSQLUpdateAction {
Object[] params;
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
this(manager, sql, (Object[]) null);
}
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql,
@Nullable List<Object> params) {
this(manager, sql, params == null ? null : params.toArray());
}
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql,
@Nullable Object[] params) {
super(manager, sql);
this.params = params;
}
@Override
public PreparedSQLUpdateActionImpl setParams(Object... params) {
this.params = params;
return this;
}
@Override
public PreparedSQLUpdateAction setParams(@Nullable Iterable<Object> params) {
if (params == null) {
return setParams((Object[]) null);
} else {
List<Object> paramsList = new ArrayList<>();
params.forEach(paramsList::add);
return setParams(paramsList.toArray());
}
}
@Override
public @NotNull Integer execute() throws SQLException {
try (Connection connection = getManager().getConnection()) {
try (PreparedStatement statement = StatementUtil.createPrepareStatement(
connection, getSQLContent(), params, returnGeneratedKeys
)) {
outputDebugMessage();
int changes = statement.executeUpdate();
if (!returnGeneratedKeys) return changes;
else {
try (ResultSet resultSet = statement.getGeneratedKeys()) {
return resultSet.next() ? resultSet.getInt(1) : -1;
}
}
}
}
}
}
@@ -0,0 +1,48 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQLUpdateActionImpl
extends AbstractSQLAction<Integer>
implements SQLUpdateAction {
boolean returnGeneratedKeys = false;
public SQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
}
@Override
public @NotNull Integer execute() throws SQLException {
try (Connection connection = getManager().getConnection()) {
try (Statement statement = connection.createStatement()) {
outputDebugMessage();
if (!returnGeneratedKeys) {
return statement.executeUpdate(getSQLContent());
} else {
statement.executeUpdate(getSQLContent(), Statement.RETURN_GENERATED_KEYS);
try (ResultSet resultSet = statement.getGeneratedKeys()) {
return resultSet.next() ? resultSet.getInt(1) : -1;
}
}
}
}
}
@Override
public SQLUpdateAction setReturnGeneratedKey(boolean returnGeneratedKey) {
this.returnGeneratedKeys = returnGeneratedKey;
return this;
}
}
@@ -0,0 +1,66 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class SQLUpdateBatchActionImpl
extends AbstractSQLAction<List<Integer>>
implements SQLUpdateBatchAction {
protected final List<String> sqlContents = new ArrayList<>();
public SQLUpdateBatchActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
this.sqlContents.add(sql);
}
@Override
public @NotNull List<String> getSQLContents() {
return this.sqlContents;
}
@Override
public SQLUpdateBatchAction addBatch(@NotNull String sql) {
Objects.requireNonNull(sql, "sql could not be null");
this.sqlContents.add(sql);
return this;
}
@Override
public @NotNull List<Integer> execute() throws SQLException {
try (Connection connection = getManager().getConnection()) {
try (Statement statement = connection.createStatement()) {
outputDebugMessage();
for (String content : this.sqlContents) {
statement.addBatch(content);
}
int[] executed = statement.executeBatch();
return Arrays.stream(executed).boxed().collect(Collectors.toList());
}
}
}
@Override
protected void outputDebugMessage() {
getManager().debug("# " + getShortID() + " -> [");
for (String content : getSQLContents()) getManager().debug(String.format(" { %s }", content));
getManager().debug("]");
}
}
@@ -0,0 +1,86 @@
package cc.carm.lib.easysql.action.query;
import cc.carm.lib.easysql.api.action.query.PreparedQueryAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.query.SQLQueryImpl;
import cc.carm.lib.easysql.util.StatementUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class PreparedQueryActionImpl extends QueryActionImpl implements PreparedQueryAction {
Consumer<PreparedStatement> handler;
Object[] params;
public PreparedQueryActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
}
@Override
public PreparedQueryActionImpl setParams(@Nullable Object... params) {
this.params = params;
return this;
}
@Override
public PreparedQueryActionImpl setParams(@Nullable Iterable<Object> params) {
if (params == null) {
return setParams((Object[]) null);
} else {
List<Object> paramsList = new ArrayList<>();
params.forEach(paramsList::add);
return setParams(paramsList.toArray());
}
}
@Override
public PreparedQueryActionImpl handleStatement(@Nullable Consumer<PreparedStatement> statement) {
this.handler = statement;
return this;
}
@Override
public @NotNull SQLQueryImpl execute() throws SQLException {
outputDebugMessage();
Connection connection = getManager().getConnection();
PreparedStatement preparedStatement;
try {
if (handler == null) {
preparedStatement = StatementUtil.createPrepareStatement(connection, getSQLContent(), this.params);
} else {
preparedStatement = connection.prepareStatement(getSQLContent());
handler.accept(preparedStatement);
}
} catch (SQLException exception) {
connection.close();
throw exception;
}
try {
long executeTime = System.currentTimeMillis();
SQLQueryImpl query = new SQLQueryImpl(
getManager(), this,
connection, preparedStatement,
preparedStatement.executeQuery(),
executeTime
);
getManager().getActiveQuery().put(getActionUUID(), query);
return query;
} catch (SQLException exception) {
preparedStatement.close();
connection.close();
throw exception;
}
}
}
@@ -0,0 +1,63 @@
package cc.carm.lib.easysql.action.query;
import cc.carm.lib.easysql.action.AbstractSQLAction;
import cc.carm.lib.easysql.api.SQLQuery;
import cc.carm.lib.easysql.api.action.query.QueryAction;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import cc.carm.lib.easysql.api.function.SQLHandler;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.query.SQLQueryImpl;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class QueryActionImpl extends AbstractSQLAction<SQLQuery> implements QueryAction {
public QueryActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
}
@Override
public @NotNull SQLQueryImpl execute() throws SQLException {
Connection connection = getManager().getConnection();
Statement statement;
try {
statement = connection.createStatement();
} catch (SQLException ex) {
connection.close();
throw ex;
}
outputDebugMessage();
try {
long executeTime = System.currentTimeMillis();
SQLQueryImpl query = new SQLQueryImpl(
getManager(), this,
connection, statement,
statement.executeQuery(getSQLContent()),
executeTime
);
getManager().getActiveQuery().put(getActionUUID(), query);
return query;
} catch (SQLException exception) {
statement.close();
connection.close();
throw exception;
}
}
@Override
public void executeAsync(SQLHandler<SQLQuery> success, SQLExceptionHandler failure) {
try (SQLQueryImpl query = execute()) {
if (success != null) success.accept(query);
} catch (SQLException exception) {
handleException(failure, exception);
}
}
}
@@ -0,0 +1,23 @@
package cc.carm.lib.easysql.builder;
import cc.carm.lib.easysql.api.SQLBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public abstract class AbstractSQLBuilder implements SQLBuilder {
@NotNull
final SQLManagerImpl sqlManager;
public AbstractSQLBuilder(@NotNull SQLManagerImpl manager) {
Objects.requireNonNull(manager, "SQLManager must not be null");
this.sqlManager = manager;
}
@Override
public @NotNull SQLManagerImpl getManager() {
return this.sqlManager;
}
}
@@ -0,0 +1,149 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.builder.ConditionalBuilder;
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.Time;
import java.sql.Timestamp;
import java.util.*;
import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote;
public abstract class AbstractConditionalBuilder<B extends ConditionalBuilder<B, T>, T extends SQLAction<?>>
extends AbstractSQLBuilder implements ConditionalBuilder<B, T> {
ArrayList<String> conditionSQLs = new ArrayList<>();
ArrayList<Object> conditionParams = new ArrayList<>();
int limit = -1;
public AbstractConditionalBuilder(@NotNull SQLManagerImpl manager) {
super(manager);
}
protected abstract B getThis();
@Override
public B setConditions(@Nullable String condition) {
this.conditionSQLs = new ArrayList<>();
this.conditionParams = new ArrayList<>();
if (condition != null) this.conditionSQLs.add(condition);
return getThis();
}
@Override
public B setConditions(
LinkedHashMap<@NotNull String, @Nullable Object> conditions
) {
conditions.forEach(this::addCondition);
return getThis();
}
@Override
public B addCondition(@Nullable String condition) {
this.conditionSQLs.add(condition);
return getThis();
}
@Override
public B addCondition(
@NotNull String columnName, @NotNull String operator, @Nullable Object queryValue
) {
Objects.requireNonNull(columnName, "columnName could not be null");
Objects.requireNonNull(operator, "operator could not be null (e.g. > or = or <) ");
addCondition(withBackQuote(columnName) + " " + operator + " ?");
this.conditionParams.add(queryValue);
return getThis();
}
@Override
public B addCondition(
@NotNull String[] columnNames, @Nullable Object[] queryValues
) {
Objects.requireNonNull(columnNames, "columnName could not be null");
if (queryValues == null || columnNames.length != queryValues.length) {
throw new RuntimeException("queryNames are not match with queryValues");
}
for (int i = 0; i < columnNames.length; i++) {
addCondition(columnNames[i], queryValues[i]);
}
return getThis();
}
@Override
public B addNotNullCondition(@NotNull String columnName) {
Objects.requireNonNull(columnName, "columnName could not be null");
return addCondition(withBackQuote(columnName) + " IS NOT NULL");
}
@Override
public B addTimeCondition(
@NotNull String columnName, @Nullable Date startDate, @Nullable Date endDate
) {
Objects.requireNonNull(columnName, "columnName could not be null");
if (startDate == null && endDate == null) return getThis(); // 都不限定时间,不用判断了
if (startDate != null) {
addCondition(withBackQuote(columnName) + " BETWEEN ? AND ?");
this.conditionParams.add(startDate);
if (endDate != null) {
this.conditionParams.add(endDate);
} else {
if (startDate instanceof java.sql.Date) {
this.conditionParams.add(new java.sql.Date(System.currentTimeMillis()));
} else if (startDate instanceof Time) {
this.conditionParams.add(new Time(System.currentTimeMillis()));
} else {
this.conditionParams.add(new Timestamp(System.currentTimeMillis()));
}
}
} else {
addCondition(columnName, "<=", endDate);
}
return getThis();
}
@Override
public B setLimit(int limit) {
this.limit = limit;
return getThis();
}
protected String buildConditionSQL() {
if (!conditionSQLs.isEmpty()) {
StringBuilder conditionBuilder = new StringBuilder();
conditionBuilder.append("WHERE").append(" ");
Iterator<String> iterator = conditionSQLs.iterator();
while (iterator.hasNext()) {
conditionBuilder.append(iterator.next());
if (iterator.hasNext()) conditionBuilder.append(" AND ");
}
return conditionBuilder.toString().trim();
} else {
return null;
}
}
protected String buildLimitSQL() {
return limit > 0 ? "LIMIT " + limit : "";
}
protected ArrayList<Object> getConditionParams() {
return conditionParams;
}
protected boolean hasConditions() {
return this.conditionSQLs != null && !this.conditionSQLs.isEmpty();
}
protected boolean hasConditionParams() {
return hasConditions() && getConditionParams() != null && !getConditionParams().isEmpty();
}
}
@@ -0,0 +1,53 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.action.PreparedSQLUpdateActionImpl;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.builder.DeleteBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote;
public class DeleteBuilderImpl
extends AbstractConditionalBuilder<DeleteBuilder, SQLAction<Integer>>
implements DeleteBuilder {
protected final String tableName;
public DeleteBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
Objects.requireNonNull(tableName);
this.tableName = tableName;
}
@Override
public PreparedSQLUpdateAction build() {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("DELETE FROM ").append(withBackQuote(getTableName()));
if (hasConditions()) sqlBuilder.append(" ").append(buildConditionSQL());
if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL());
return new PreparedSQLUpdateActionImpl(
getManager(), sqlBuilder.toString(),
hasConditionParams() ? getConditionParams() : null
);
}
@Override
public String getTableName() {
return tableName;
}
@Override
protected DeleteBuilderImpl getThis() {
return this;
}
}
@@ -0,0 +1,57 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.builder.InsertBuilder;
import cc.carm.lib.easysql.builder.AbstractSQLBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote;
public abstract class InsertBuilderImpl<T extends SQLAction<?>>
extends AbstractSQLBuilder implements InsertBuilder<T> {
protected final String tableName;
public InsertBuilderImpl(@NotNull SQLManagerImpl manager, String tableName) {
super(manager);
Objects.requireNonNull(tableName);
this.tableName = tableName;
}
protected static String buildSQL(String tableName, List<String> columnNames) {
return buildSQL("INSERT IGNORE INTO", tableName, columnNames);
}
protected static String buildSQL(String sqlPrefix, String tableName, List<String> columnNames) {
int valueLength = columnNames.size();
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append(sqlPrefix).append(" ").append(withBackQuote(tableName)).append("(");
Iterator<String> iterator = columnNames.iterator();
while (iterator.hasNext()) {
sqlBuilder.append(withBackQuote(iterator.next()));
if (iterator.hasNext()) sqlBuilder.append(", ");
}
sqlBuilder.append(") VALUES (");
for (int i = 0; i < valueLength; i++) {
sqlBuilder.append("?");
if (i != valueLength - 1) {
sqlBuilder.append(", ");
}
}
sqlBuilder.append(")");
return sqlBuilder.toString();
}
@Override
public String getTableName() {
return tableName;
}
}
@@ -0,0 +1,39 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.action.query.PreparedQueryActionImpl;
import cc.carm.lib.easysql.action.query.QueryActionImpl;
import cc.carm.lib.easysql.api.action.query.PreparedQueryAction;
import cc.carm.lib.easysql.api.action.query.QueryAction;
import cc.carm.lib.easysql.api.builder.QueryBuilder;
import cc.carm.lib.easysql.api.builder.TableQueryBuilder;
import cc.carm.lib.easysql.builder.AbstractSQLBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class QueryBuilderImpl extends AbstractSQLBuilder implements QueryBuilder {
public QueryBuilderImpl(@NotNull SQLManagerImpl manager) {
super(manager);
}
@Override
@Deprecated
public QueryAction withSQL(@NotNull String sql) {
Objects.requireNonNull(sql, "sql could not be null");
return new QueryActionImpl(getManager(), sql);
}
@Override
public PreparedQueryAction withPreparedSQL(@NotNull String sql) {
Objects.requireNonNull(sql, "sql could not be null");
return new PreparedQueryActionImpl(getManager(), sql);
}
@Override
public TableQueryBuilder inTable(@NotNull String tableName) {
Objects.requireNonNull(tableName, "tableName could not be null");
return new TableQueryBuilderImpl(getManager(), tableName);
}
}
@@ -0,0 +1,29 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.builder.ReplaceBuilder;
import cc.carm.lib.easysql.builder.AbstractSQLBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public abstract class ReplaceBuilderImpl<T extends SQLAction<?>>
extends AbstractSQLBuilder implements ReplaceBuilder<T> {
protected final @NotNull String tableName;
public ReplaceBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
}
protected static String buildSQL(String tableName, List<String> columnNames) {
return InsertBuilderImpl.buildSQL("REPLACE INTO", tableName, columnNames);
}
@Override
public @NotNull String getTableName() {
return tableName;
}
}
@@ -0,0 +1,153 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.action.SQLUpdateActionImpl;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.builder.TableAlterBuilder;
import cc.carm.lib.easysql.api.enums.IndexType;
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.util.Objects;
import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote;
import static cc.carm.lib.easysql.api.SQLBuilder.withQuote;
public class TableAlterBuilderImpl extends AbstractSQLBuilder implements TableAlterBuilder {
protected final @NotNull String tableName;
public TableAlterBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
}
public @NotNull String getTableName() {
return tableName;
}
@Override
public SQLAction<Integer> renameTo(@NotNull String newTableName) {
Objects.requireNonNull(newTableName, "table name could not be null");
return new SQLUpdateActionImpl(getManager(),
"ALTER TABLE " + withBackQuote(tableName) + " RENAME TO " + withBackQuote(newTableName)
);
}
@Override
public SQLAction<Integer> changeComment(@NotNull String newTableComment) {
Objects.requireNonNull(newTableComment, "table comment could not be null");
return new SQLUpdateActionImpl(getManager(),
"ALTER TABLE " + withBackQuote(getTableName()) + " COMMENT " + withQuote(newTableComment)
);
}
@Override
public SQLAction<Integer> setAutoIncrementIndex(int index) {
return new SQLUpdateActionImpl(getManager(),
"ALTER TABLE " + withBackQuote(getTableName()) + " AUTO_INCREMENT=" + index
);
}
@Override
public SQLAction<Integer> addIndex(@NotNull IndexType indexType, @Nullable String indexName,
@NotNull String columnName, @NotNull String... moreColumns) {
Objects.requireNonNull(indexType, "indexType could not be null");
Objects.requireNonNull(columnName, "column names could not be null");
Objects.requireNonNull(moreColumns, "column names could not be null");
return createAction(
"ALTER TABLE " + withBackQuote(getTableName()) + " ADD "
+ TableCreateBuilderImpl.buildIndexSettings(indexType, indexName, columnName, moreColumns)
);
}
@Override
public SQLAction<Integer> dropIndex(@NotNull String indexName) {
Objects.requireNonNull(indexName, "indexName could not be null");
return createAction(
"ALTER TABLE " + withBackQuote(getTableName()) + " DROP INDEX " + withBackQuote(indexName)
);
}
@Override
public SQLAction<Integer> dropForeignKey(@NotNull String keySymbol) {
Objects.requireNonNull(keySymbol, "keySymbol could not be null");
return createAction(
"ALTER TABLE " + withBackQuote(getTableName()) + " DROP FOREIGN KEY " + withBackQuote(keySymbol)
);
}
@Override
public SQLAction<Integer> dropPrimaryKey() {
return createAction(
"ALTER TABLE " + withBackQuote(getTableName()) + " DROP PRIMARY KEY"
);
}
@Override
public SQLAction<Integer> addColumn(@NotNull String columnName, @NotNull String settings, @Nullable String afterColumn) {
Objects.requireNonNull(columnName, "columnName could not be null");
Objects.requireNonNull(settings, "settings could not be null");
String orderSettings = null;
if (afterColumn != null) {
if (afterColumn.length() > 0) {
orderSettings = "AFTER " + withBackQuote(afterColumn);
} else {
orderSettings = "FIRST";
}
}
return createAction(
"ALTER TABLE " + withBackQuote(getTableName()) + " ADD " + withBackQuote(columnName) + " " + settings
+ (orderSettings != null ? " " + orderSettings : "")
);
}
@Override
public SQLAction<Integer> renameColumn(@NotNull String columnName, @NotNull String newName) {
Objects.requireNonNull(columnName, "columnName could not be null");
Objects.requireNonNull(newName, "please specify new column name");
return createAction(
"ALTER TABLE " + withBackQuote(getTableName()) + " RENAME COLUMN " + withBackQuote(columnName) + " TO " + withBackQuote(newName)
);
}
@Override
public SQLAction<Integer> modifyColumn(@NotNull String columnName, @NotNull String settings) {
Objects.requireNonNull(columnName, "columnName could not be null");
Objects.requireNonNull(settings, "please specify new column settings");
return createAction(
"ALTER TABLE " + withBackQuote(getTableName()) + " MODIFY COLUMN " + withBackQuote(columnName) + " " + settings
);
}
@Override
public SQLAction<Integer> removeColumn(@NotNull String columnName) {
Objects.requireNonNull(columnName, "columnName could not be null");
return createAction(
"ALTER TABLE " + withBackQuote(getTableName()) + " DROP " + withBackQuote(columnName)
);
}
@Override
public SQLAction<Integer> setColumnDefault(@NotNull String columnName, @NotNull String defaultValue) {
Objects.requireNonNull(columnName, "columnName could not be null");
Objects.requireNonNull(defaultValue, "defaultValue could not be null, if you need to remove the default value, please use #removeColumnDefault().");
return createAction(
"ALTER TABLE " + withBackQuote(getTableName()) + " ALTER " + withBackQuote(columnName) + " SET DEFAULT " + defaultValue
);
}
@Override
public SQLAction<Integer> removeColumnDefault(@NotNull String columnName) {
Objects.requireNonNull(columnName, "columnName could not be null");
return createAction(
"ALTER TABLE " + withBackQuote(getTableName()) + " ALTER " + withBackQuote(columnName) + " DROP DEFAULT"
);
}
private SQLUpdateActionImpl createAction(@NotNull String sql) {
return new SQLUpdateActionImpl(getManager(), sql);
}
}
@@ -0,0 +1,172 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.action.SQLUpdateActionImpl;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.api.builder.TableCreateBuilder;
import cc.carm.lib.easysql.api.enums.ForeignKeyRule;
import cc.carm.lib.easysql.api.enums.IndexType;
import cc.carm.lib.easysql.api.enums.NumberType;
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.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote;
import static cc.carm.lib.easysql.api.SQLBuilder.withQuote;
public class TableCreateBuilderImpl extends AbstractSQLBuilder implements TableCreateBuilder {
protected final @NotNull String tableName;
@NotNull
final List<String> indexes = new ArrayList<>();
@NotNull
final List<String> foreignKeys = new ArrayList<>();
@NotNull List<String> columns = new ArrayList<>();
@NotNull String tableSettings = defaultTablesSettings();
@Nullable String tableComment;
public TableCreateBuilderImpl(SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
}
protected static String buildIndexSettings(@NotNull IndexType indexType, @Nullable String indexName,
@NotNull String columnName, @NotNull String... moreColumns) {
Objects.requireNonNull(indexType, "indexType could not be null");
Objects.requireNonNull(columnName, "column names could not be null");
Objects.requireNonNull(moreColumns, "column names could not be null");
StringBuilder indexBuilder = new StringBuilder();
indexBuilder.append(indexType.getName()).append(" ");
if (indexName != null) {
indexBuilder.append(withBackQuote(indexName));
}
indexBuilder.append("(");
indexBuilder.append(withBackQuote(columnName));
if (moreColumns.length > 0) {
indexBuilder.append(", ");
for (int i = 0; i < moreColumns.length; i++) {
indexBuilder.append(withBackQuote(moreColumns[i]));
if (i != moreColumns.length - 1) indexBuilder.append(", ");
}
}
indexBuilder.append(")");
return indexBuilder.toString();
}
@Override
public @NotNull String getTableName() {
return this.tableName;
}
@Override
public @NotNull String getTableSettings() {
return this.tableSettings;
}
@Override
public SQLUpdateAction build() {
StringBuilder createSQL = new StringBuilder();
createSQL.append("CREATE TABLE IF NOT EXISTS ").append(withBackQuote(tableName));
createSQL.append("(");
createSQL.append(String.join(", ", columns));
if (indexes.size() > 0) {
createSQL.append(", ");
createSQL.append(String.join(", ", indexes));
}
if (foreignKeys.size() > 0) {
createSQL.append(", ");
createSQL.append(String.join(", ", foreignKeys));
}
createSQL.append(") ").append(getTableSettings());
if (tableComment != null) {
createSQL.append(" COMMENT ").append(withQuote(tableComment));
}
return new SQLUpdateActionImpl(getManager(), createSQL.toString());
}
@Override
public TableCreateBuilder addColumn(@NotNull String column) {
Objects.requireNonNull(column, "column could not be null");
this.columns.add(column);
return this;
}
@Override
public TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType,
boolean asPrimaryKey, boolean unsigned) {
return addColumn(columnName,
(numberType == null ? NumberType.INT : numberType).name()
+ (unsigned ? " UNSIGNED " : " ")
+ "NOT NULL AUTO_INCREMENT " + (asPrimaryKey ? "PRIMARY KEY" : "UNIQUE KEY")
);
}
@Override
public TableCreateBuilder setIndex(@NotNull IndexType type, @Nullable String indexName,
@NotNull String columnName, @NotNull String... moreColumns) {
Objects.requireNonNull(columnName, "columnName could not be null");
this.indexes.add(buildIndexSettings(type, indexName, columnName, moreColumns));
return this;
}
@Override
public TableCreateBuilder addForeignKey(@NotNull String tableColumn, @Nullable String constraintName,
@NotNull String foreignTable, @NotNull String foreignColumn,
@Nullable ForeignKeyRule updateRule, @Nullable ForeignKeyRule deleteRule) {
Objects.requireNonNull(tableColumn, "tableColumn could not be null");
Objects.requireNonNull(foreignTable, "foreignTable could not be null");
Objects.requireNonNull(foreignColumn, "foreignColumn could not be null");
StringBuilder keyBuilder = new StringBuilder();
keyBuilder.append("CONSTRAINT ");
if (constraintName == null) {
keyBuilder.append(withBackQuote("fk_" + tableColumn + "_" + foreignTable));
} else {
keyBuilder.append(withBackQuote(constraintName));
}
keyBuilder.append(" ");
keyBuilder.append("FOREIGN KEY (").append(withBackQuote(tableColumn)).append(") ");
keyBuilder.append("REFERENCES ").append(withBackQuote(foreignTable)).append("(").append(withBackQuote(foreignColumn)).append(")");
if (updateRule != null) keyBuilder.append(" ON UPDATE ").append(updateRule.getRuleName());
if (deleteRule != null) keyBuilder.append(" ON DELETE ").append(deleteRule.getRuleName());
this.foreignKeys.add(keyBuilder.toString());
return this;
}
@Override
public TableCreateBuilder setColumns(@NotNull String... columns) {
Objects.requireNonNull(columns, "columns could not be null");
this.columns = Arrays.asList(columns);
return this;
}
@Override
public TableCreateBuilder setTableSettings(@NotNull String settings) {
Objects.requireNonNull(settings, "settings could not be null");
this.tableSettings = settings;
return this;
}
@Override
public TableCreateBuilder setTableComment(@Nullable String comment) {
this.tableComment = comment;
return this;
}
}
@@ -0,0 +1,94 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.action.query.PreparedQueryActionImpl;
import cc.carm.lib.easysql.api.action.query.PreparedQueryAction;
import cc.carm.lib.easysql.api.builder.TableQueryBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote;
public class TableQueryBuilderImpl
extends AbstractConditionalBuilder<TableQueryBuilder, PreparedQueryAction>
implements TableQueryBuilder {
protected final @NotNull String tableName;
String[] columns;
@Nullable String orderBy;
int[] pageLimit;
public TableQueryBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
}
@Override
public PreparedQueryActionImpl build() {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("SELECT").append(" ");
if (columns == null || columns.length < 1) {
sqlBuilder.append("*");
} else {
for (int i = 0; i < columns.length; i++) {
String name = columns[i];
sqlBuilder.append(withBackQuote(name));
if (i != columns.length - 1) {
sqlBuilder.append(",");
}
}
}
sqlBuilder.append(" ").append("FROM").append(" ").append(withBackQuote(tableName));
if (hasConditions()) sqlBuilder.append(" ").append(buildConditionSQL());
if (orderBy != null) sqlBuilder.append(" ").append(orderBy);
if (pageLimit != null && pageLimit.length == 2) {
sqlBuilder.append(" LIMIT ").append(pageLimit[0]).append(",").append(pageLimit[1]);
} else if (limit > 0) {
sqlBuilder.append(" ").append(buildLimitSQL());
}
return new PreparedQueryActionImpl(getManager(), sqlBuilder.toString())
.setParams(hasConditionParams() ? getConditionParams() : null);
}
@Override
public @NotNull String getTableName() {
return tableName;
}
@Override
public TableQueryBuilderImpl selectColumns(@NotNull String... columnNames) {
Objects.requireNonNull(columnNames, "columnNames could not be null");
this.columns = columnNames;
return this;
}
@Override
public TableQueryBuilder orderBy(@NotNull String columnName, boolean asc) {
Objects.requireNonNull(columnName, "columnName could not be null");
this.orderBy = "ORDER BY " + withBackQuote(columnName) + " " + (asc ? "ASC" : "DESC");
return this;
}
@Override
public TableQueryBuilder setPageLimit(int start, int end) {
this.pageLimit = new int[]{start, end};
return this;
}
@Override
protected TableQueryBuilderImpl getThis() {
return this;
}
}
@@ -0,0 +1,89 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.action.PreparedSQLUpdateActionImpl;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.builder.UpdateBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote;
public class UpdateBuilderImpl
extends AbstractConditionalBuilder<UpdateBuilder, SQLAction<Integer>>
implements UpdateBuilder {
protected final @NotNull String tableName;
@NotNull LinkedHashMap<String, Object> columnData;
public UpdateBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
this.columnData = new LinkedHashMap<>();
}
@Override
public PreparedSQLUpdateAction build() {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("UPDATE ").append(withBackQuote(getTableName())).append(" SET ");
Iterator<String> iterator = this.columnData.keySet().iterator();
while (iterator.hasNext()) {
sqlBuilder.append(withBackQuote(iterator.next())).append(" = ?");
if (iterator.hasNext()) sqlBuilder.append(" , ");
}
List<Object> allParams = new ArrayList<>(this.columnData.values());
if (hasConditions()) {
sqlBuilder.append(" ").append(buildConditionSQL());
allParams.addAll(getConditionParams());
}
if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL());
return new PreparedSQLUpdateActionImpl(getManager(), sqlBuilder.toString(), allParams);
}
@Override
public @NotNull String getTableName() {
return tableName;
}
@Override
public UpdateBuilder addColumnValue(@NotNull String columnName, Object columnValue) {
Objects.requireNonNull(columnName, "columnName could not be null");
this.columnData.put(columnName, columnValue);
return this;
}
@Override
public UpdateBuilder setColumnValues(LinkedHashMap<String, Object> columnData) {
this.columnData = columnData;
return this;
}
@Override
public UpdateBuilder setColumnValues(@NotNull String[] columnNames, @Nullable Object[] columnValues) {
Objects.requireNonNull(columnNames, "columnName could not be null");
if (columnNames.length != columnValues.length) {
throw new RuntimeException("columnNames are not match with columnValues");
}
LinkedHashMap<String, Object> columnData = new LinkedHashMap<>();
for (int i = 0; i < columnNames.length; i++) {
columnData.put(columnNames[i], columnValues[i]);
}
return setColumnValues(columnData);
}
@Override
protected UpdateBuilder getThis() {
return this;
}
}
@@ -0,0 +1,194 @@
package cc.carm.lib.easysql.manager;
import cc.carm.lib.easysql.action.PreparedSQLBatchUpdateActionImpl;
import cc.carm.lib.easysql.action.PreparedSQLUpdateActionImpl;
import cc.carm.lib.easysql.action.SQLUpdateActionImpl;
import cc.carm.lib.easysql.action.SQLUpdateBatchActionImpl;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLQuery;
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.builder.impl.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
import java.util.logging.Logger;
public class SQLManagerImpl implements SQLManager {
private final Logger LOGGER;
private final DataSource dataSource;
private final ConcurrentHashMap<UUID, SQLQuery> activeQuery = new ConcurrentHashMap<>();
protected ExecutorService executorPool;
@NotNull Supplier<Boolean> debugMode = () -> Boolean.FALSE;
public SQLManagerImpl(@NotNull DataSource dataSource) {
this(dataSource, null);
}
public SQLManagerImpl(@NotNull DataSource dataSource, @Nullable String name) {
String managerName = "SQLManager" + (name != null ? "#" + name : "");
this.LOGGER = Logger.getLogger(managerName);
this.dataSource = dataSource;
this.executorPool = Executors.newFixedThreadPool(3, r -> {
Thread thread = new Thread(r, managerName);
thread.setDaemon(true);
return thread;
});
}
@Override
public boolean isDebugMode() {
return this.debugMode.get();
}
@Override
public void setDebugMode(@NotNull Supplier<@NotNull Boolean> debugMode) {
this.debugMode = debugMode;
}
public void debug(String msg) {
if (isDebugMode()) getLogger().info("[DEBUG] " + msg);
}
@Override
public Logger getLogger() {
return LOGGER;
}
public ExecutorService getExecutorPool() {
return executorPool;
}
@Override
public @NotNull DataSource getDataSource() {
return this.dataSource;
}
@Override
public @NotNull Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
@Override
public @NotNull Map<UUID, SQLQuery> getActiveQuery() {
return this.activeQuery;
}
@Override
public Integer executeSQL(String sql) {
return new SQLUpdateActionImpl(this, sql).execute(null);
}
@Override
public Integer executeSQL(String sql, Object[] params) {
return new PreparedSQLUpdateActionImpl(this, sql, params).execute(null);
}
@Override
public List<Integer> executeSQLBatch(String sql, Iterable<Object[]> paramsBatch) {
return new PreparedSQLBatchUpdateActionImpl(this, sql)
.setAllParams(paramsBatch)
.execute(null);
}
@Override
public List<Integer> executeSQLBatch(@NotNull String sql, String... moreSQL) {
SQLUpdateBatchAction action = new SQLUpdateBatchActionImpl(this, sql);
if (moreSQL != null && moreSQL.length > 0) {
Arrays.stream(moreSQL).forEach(action::addBatch);
}
return action.execute(null);
}
@Override
public @Nullable List<Integer> executeSQLBatch(@NotNull Iterable<String> sqlBatch) {
Iterator<String> iterator = sqlBatch.iterator();
if (!iterator.hasNext()) return null; // PLEASE GIVE IT SOMETHING
SQLUpdateBatchAction action = new SQLUpdateBatchActionImpl(this, iterator.next());
while (iterator.hasNext()) {
action.addBatch(iterator.next());
}
return action.execute(null);
}
@Override
public TableCreateBuilder createTable(@NotNull String tableName) {
return new TableCreateBuilderImpl(this, tableName);
}
@Override
public TableAlterBuilder alterTable(@NotNull String tableName) {
return new TableAlterBuilderImpl(this, tableName);
}
@Override
public QueryBuilder createQuery() {
return new QueryBuilderImpl(this);
}
@Override
public InsertBuilder<PreparedSQLUpdateBatchAction> createInsertBatch(@NotNull String tableName) {
return new InsertBuilderImpl<PreparedSQLUpdateBatchAction>(this, tableName) {
@Override
public PreparedSQLUpdateBatchAction setColumnNames(List<String> columnNames) {
return new PreparedSQLBatchUpdateActionImpl(getManager(), buildSQL(getTableName(), columnNames));
}
};
}
@Override
public InsertBuilder<PreparedSQLUpdateAction> createInsert(@NotNull String tableName) {
return new InsertBuilderImpl<PreparedSQLUpdateAction>(this, tableName) {
@Override
public PreparedSQLUpdateAction setColumnNames(List<String> columnNames) {
return new PreparedSQLUpdateActionImpl(getManager(), buildSQL(getTableName(), columnNames));
}
};
}
@Override
public ReplaceBuilder<PreparedSQLUpdateBatchAction> createReplaceBatch(@NotNull String tableName) {
return new ReplaceBuilderImpl<PreparedSQLUpdateBatchAction>(this, tableName) {
@Override
public PreparedSQLUpdateBatchAction setColumnNames(List<String> columnNames) {
return new PreparedSQLBatchUpdateActionImpl(getManager(), buildSQL(getTableName(), columnNames));
}
};
}
@Override
public ReplaceBuilder<PreparedSQLUpdateAction> createReplace(@NotNull String tableName) {
return new ReplaceBuilderImpl<PreparedSQLUpdateAction>(this, tableName) {
@Override
public PreparedSQLUpdateAction setColumnNames(List<String> columnNames) {
return new PreparedSQLUpdateActionImpl(getManager(), buildSQL(getTableName(), columnNames));
}
};
}
@Override
public UpdateBuilder createUpdate(@NotNull String tableName) {
return new UpdateBuilderImpl(this, tableName);
}
@Override
public DeleteBuilder createDelete(@NotNull String tableName) {
return new DeleteBuilderImpl(this, tableName);
}
}
@@ -0,0 +1,93 @@
package cc.carm.lib.easysql.query;
import cc.carm.lib.easysql.action.query.QueryActionImpl;
import cc.carm.lib.easysql.api.SQLQuery;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQLQueryImpl implements SQLQuery {
protected final long executeTime;
protected final SQLManagerImpl sqlManager;
final Connection connection;
final Statement statement;
final ResultSet resultSet;
protected QueryActionImpl queryAction;
public SQLQueryImpl(
SQLManagerImpl sqlManager, QueryActionImpl queryAction,
Connection connection, Statement statement, ResultSet resultSet
) {
this(sqlManager, queryAction, connection, statement, resultSet, System.currentTimeMillis());
}
public SQLQueryImpl(
SQLManagerImpl sqlManager, QueryActionImpl queryAction,
Connection connection, Statement statement, ResultSet resultSet,
long executeTime
) {
this.executeTime = executeTime;
this.sqlManager = sqlManager;
this.queryAction = queryAction;
this.connection = connection;
this.statement = statement;
this.resultSet = resultSet;
}
@Override
public long getExecuteTime() {
return this.executeTime;
}
@Override
public SQLManagerImpl getManager() {
return this.sqlManager;
}
@Override
public QueryActionImpl getAction() {
return this.queryAction;
}
@Override
public ResultSet getResultSet() {
return this.resultSet;
}
@Override
public String getSQLContent() {
return getAction().getSQLContent();
}
@Override
public void close() {
try {
if (getResultSet() != null && !getResultSet().isClosed()) getResultSet().close();
if (getStatement() != null && !getStatement().isClosed()) getStatement().close();
if (getConnection() != null && !getConnection().isClosed()) getConnection().close();
getManager().debug("#" + getAction().getShortID() +
" -> finished after " + (System.currentTimeMillis() - getExecuteTime()) + " ms."
);
getManager().getActiveQuery().remove(getAction().getActionUUID());
} catch (SQLException e) {
getAction().handleException(getAction().defaultExceptionHandler(), e);
}
this.queryAction = null;
}
@Override
public Statement getStatement() {
return this.statement;
}
@Override
public Connection getConnection() {
return this.connection;
}
}
@@ -0,0 +1,210 @@
package cc.carm.lib.easysql.util;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class StatementUtil {
/**
* 创建一个 {@link PreparedStatement} 。
*
* @param connection 数据库连接
* @param sql SQL语句,使用"?"做为占位符
* @param params "?"所代表的对应参数列表
* @return 完成参数填充的 {@link PreparedStatement}
*/
public static PreparedStatement createPrepareStatement(
Connection connection, String sql, Object[] params
) throws SQLException {
return createPrepareStatement(connection, sql, params, false);
}
/**
* 创建一个 {@link PreparedStatement} 。
*
* @param connection 数据库连接
* @param sql SQL语句,使用"?"做为占位符
* @param params "?"所代表的对应参数列表
* @param returnGeneratedKey 是否会返回自增主键
* @return 完成参数填充的 {@link PreparedStatement}
*/
public static PreparedStatement createPrepareStatement(
Connection connection, String sql, Object[] params, boolean returnGeneratedKey
) throws SQLException {
sql = sql.trim();
PreparedStatement statement = connection.prepareStatement(sql, returnGeneratedKey ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS);
Map<Integer, Integer> nullTypeMap = new HashMap<>();
if (params != null) fillParams(statement, Arrays.asList(params), nullTypeMap);
statement.addBatch();
return statement;
}
/**
* 创建批量操作的一个 {@link PreparedStatement} 。
*
* @param connection 数据库连接
* @param sql SQL语句,使用"?"做为占位符
* @param paramsBatch "?"所代表的对应参数列表
* @return 完成参数填充的 {@link PreparedStatement}
*/
public static PreparedStatement createPrepareStatementBatch(
Connection connection, String sql, Iterable<Object[]> paramsBatch
) throws SQLException {
return createPrepareStatementBatch(connection, sql, paramsBatch, false);
}
/**
* 创建批量操作的一个 {@link PreparedStatement} 。
*
* @param connection 数据库连接
* @param sql SQL语句,使用"?"做为占位符
* @param paramsBatch "?"所代表的对应参数列表
* @param returnGeneratedKey 是否会返回自增主键
* @return 完成参数填充的 {@link PreparedStatement}
*/
public static PreparedStatement createPrepareStatementBatch(
Connection connection, String sql, Iterable<Object[]> paramsBatch, boolean returnGeneratedKey
) throws SQLException {
sql = sql.trim();
PreparedStatement statement = connection.prepareStatement(sql, returnGeneratedKey ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS);
Map<Integer, Integer> nullTypeMap = new HashMap<>();
for (Object[] params : paramsBatch) {
fillParams(statement, Arrays.asList(params), nullTypeMap);
statement.addBatch();
}
return statement;
}
/**
* 填充PreparedStatement的参数。
*
* @param statement PreparedStatement
* @param params SQL参数
* @return {@link PreparedStatement} 填充参数后的PreparedStatement
* @throws SQLException SQL执行异常
*/
public static PreparedStatement fillParams(
PreparedStatement statement, Iterable<?> params
) throws SQLException {
return fillParams(statement, params, null);
}
/**
* 填充PreparedStatement的参数。
*
* @param statement PreparedStatement
* @param params SQL参数
* @param nullCache null参数的类型缓存,避免循环中重复获取类型
* @return 完成参数填充的 {@link PreparedStatement}
*/
public static PreparedStatement fillParams(
PreparedStatement statement, Iterable<?> params, Map<Integer, Integer> nullCache
) throws SQLException {
if (null == params) {
return statement;// 无参数
}
int paramIndex = 1;//第一个参数从1计数
for (Object param : params) {
setParam(statement, paramIndex++, param, nullCache);
}
return statement;
}
/**
* 获取null字段对应位置的数据类型
* 如果类型获取失败将使用默认的 {@link Types#VARCHAR}
*
* @param statement {@link PreparedStatement}
* @param paramIndex 参数序列,第一位从1开始
* @return 数据类型,默认为 {@link Types#VARCHAR}
*/
public static int getNullType(PreparedStatement statement, int paramIndex) {
try {
ParameterMetaData pmd = statement.getParameterMetaData();
return pmd.getParameterType(paramIndex);
} catch (SQLException ignore) {
return Types.VARCHAR;
}
}
/**
* 为 {@link PreparedStatement} 设置单个参数
*
* @param preparedStatement {@link PreparedStatement}
* @param paramIndex 参数序列,从1开始
* @param param 参数,不能为{@code null}
* @param nullCache 用于缓存参数为null位置的类型,避免重复获取
*/
private static void setParam(
PreparedStatement preparedStatement, int paramIndex, Object param,
Map<Integer, Integer> nullCache
) throws SQLException {
if (param == null) {
Integer type = (null == nullCache) ? null : nullCache.get(paramIndex);
if (null == type) {
type = getNullType(preparedStatement, paramIndex);
if (null != nullCache) {
nullCache.put(paramIndex, type);
}
}
preparedStatement.setNull(paramIndex, type);
}
// 针对UUID特殊处理,避免元数据直接传入
if (param instanceof UUID) {
preparedStatement.setString(paramIndex, param.toString());
return;
}
// 针对StringBuilder或StringBuffer进行处理,避免元数据传入
if (param instanceof StringBuilder || param instanceof StringBuffer) {
preparedStatement.setString(paramIndex, param.toString());
return;
}
// 日期特殊处理,默认按照时间戳传入,避免精度丢失
if (param instanceof java.util.Date) {
if (param instanceof Date) {
preparedStatement.setDate(paramIndex, (Date) param);
} else if (param instanceof Time) {
preparedStatement.setTime(paramIndex, (Time) param);
} else {
preparedStatement.setTimestamp(paramIndex, new Timestamp(((java.util.Date) param).getTime()));
}
return;
}
// 针对大数字类型的特殊处理
if (param instanceof Number) {
if (param instanceof BigDecimal) {
// BigDecimal的转换交给JDBC驱动处理
preparedStatement.setBigDecimal(paramIndex, (BigDecimal) param);
return;
} else if (param instanceof BigInteger) {
preparedStatement.setBigDecimal(paramIndex, new BigDecimal((BigInteger) param));
return;
}
// 其它数字类型按照默认类型传入
}
if (param instanceof Enum) {
//枚举类采用 name()
preparedStatement.setString(paramIndex, ((Enum<?>) param).name());
return;
}
// 其它参数类型直接传入
preparedStatement.setObject(paramIndex, param);
}
}