1
mirror of https://github.com/CarmJos/EasySQL.git synced 2026-06-04 15:28:20 +08:00

[v0.3.0] 版本更新

- [A] 添加 TableAlertBuilder 用于快捷修改表的相关设定
- [A] 为 TableCreateBuilder 添加数个方法,包含创建索引、自增主键与外键。
- [R] 修改部分Builder的参数值,为泛型添加限定。
This commit is contained in:
2022-01-25 23:18:05 +08:00
parent d29d06053c
commit cf91a10b6d
39 changed files with 1454 additions and 645 deletions
+8 -9
View File
@@ -5,10 +5,17 @@
<parent>
<artifactId>easysql-parent</artifactId>
<groupId>cc.carm.lib</groupId>
<version>0.2.10</version>
<version>0.3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<artifactId>easysql-impl</artifactId>
<packaging>jar</packaging>
@@ -45,14 +52,6 @@
<url>${project.url}/actions/workflows/maven.yml</url>
</ciManagement>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>
<dependencies>
<dependency>
@@ -5,10 +5,8 @@ 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 org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.Optional;
import java.util.UUID;
public abstract class AbstractSQLAction<T> implements SQLAction<T> {
@@ -20,8 +18,6 @@ public abstract class AbstractSQLAction<T> implements SQLAction<T> {
protected @NotNull String sqlContent;
protected static @Nullable SQLExceptionHandler exceptionHandler = null;
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql) {
this(manager, sql, System.currentTimeMillis());
}
@@ -69,10 +65,11 @@ public abstract class AbstractSQLAction<T> implements SQLAction<T> {
}
protected void outputDebugMessage() {
getManager().debug("#" + getShortID() + " ->" + getSQLContent());
getManager().debug("#" + getShortID() + " -> { " + getSQLContent() + " }");
}
@Override
@SuppressWarnings("FutureReturnValueIgnored")
public void executeAsync(SQLHandler<T> success, SQLExceptionHandler failure) {
getManager().getExecutorPool().submit(() -> {
try {
@@ -39,6 +39,7 @@ public class SQLUpdateBatchActionImpl
Connection connection = getManager().getConnection();
Statement statement = connection.createStatement();
outputDebugMessage();
for (String content : this.sqlContents) {
statement.addBatch(content);
}
@@ -50,4 +51,13 @@ public class SQLUpdateBatchActionImpl
return returnedValues;
}
@Override
protected void outputDebugMessage() {
getManager().debug("#" + getShortID() + " -> {");
for (String content : getSQLContents()) getManager().debug(" " + content);
getManager().debug("}");
}
}
@@ -50,8 +50,9 @@ public class PreparedQueryActionImpl extends QueryActionImpl implements Prepared
@Override
public @NotNull SQLQueryImpl execute() throws SQLException {
outputDebugMessage();
Connection connection = getManager().getConnection();
getManager().debug("#" + getShortID() + " ->" + getSQLContent());
PreparedStatement preparedStatement;
if (handler == null) {
preparedStatement = StatementUtil.createPrepareStatement(connection, getSQLContent(), this.params);
@@ -60,8 +61,14 @@ public class PreparedQueryActionImpl extends QueryActionImpl implements Prepared
handler.accept(preparedStatement);
}
long executeTime = System.currentTimeMillis();
ResultSet resultSet = preparedStatement.executeQuery();
return new SQLQueryImpl(getManager(), this, connection, preparedStatement, resultSet);
return new SQLQueryImpl(
getManager(), this,
connection, preparedStatement, resultSet,
executeTime
);
}
}
@@ -1,8 +1,8 @@
package cc.carm.lib.easysql.action.query;
import cc.carm.lib.easysql.action.AbstractSQLAction;
import cc.carm.lib.easysql.api.action.query.QueryAction;
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;
@@ -22,13 +22,20 @@ public class QueryActionImpl extends AbstractSQLAction<SQLQuery> implements Quer
@Override
public @NotNull SQLQueryImpl execute() throws SQLException {
Connection connection = getManager().getConnection();
Statement statement = connection.createStatement();
outputDebugMessage();
long executeTime = System.currentTimeMillis();
ResultSet resultSet = statement.executeQuery(getSQLContent());
SQLQueryImpl query = new SQLQueryImpl(getManager(), this, connection, statement, resultSet);
SQLQueryImpl query = new SQLQueryImpl(
getManager(), this,
connection, statement, resultSet,
executeTime
);
getManager().getActiveQuery().put(getActionUUID(), query);
return query;
@@ -1,5 +1,6 @@
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;
@@ -13,132 +14,132 @@ import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
public abstract class AbstractConditionalBuilder<B extends ConditionalBuilder<B, T>, T>
extends AbstractSQLBuilder implements ConditionalBuilder<B, T> {
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;
ArrayList<String> conditionSQLs = new ArrayList<>();
ArrayList<Object> conditionParams = new ArrayList<>();
int limit = -1;
public AbstractConditionalBuilder(@NotNull SQLManagerImpl manager) {
super(manager);
}
public AbstractConditionalBuilder(@NotNull SQLManagerImpl manager) {
super(manager);
}
protected abstract B getThis();
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(@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 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(@Nullable String condition) {
this.conditionSQLs.add(condition);
return getThis();
}
@Override
public B addCondition(
@NotNull String queryName, @NotNull String operator, @Nullable Object queryValue
) {
addCondition("`" + queryName + "` " + operator + " ?");
this.conditionParams.add(queryValue);
return getThis();
}
@Override
public B addCondition(
@NotNull String queryName, @NotNull String operator, @Nullable Object queryValue
) {
addCondition("`" + queryName + "` " + operator + " ?");
this.conditionParams.add(queryValue);
return getThis();
}
@Override
public B addCondition(
@NotNull String[] queryNames, @Nullable Object[] queryValues
) {
if (queryNames.length != queryValues.length) {
throw new RuntimeException("queryNames are not match with queryValues");
}
for (int i = 0; i < queryNames.length; i++) {
addCondition(queryNames[i], queryValues[i]);
}
return getThis();
}
@Override
public B addCondition(
@NotNull String[] queryNames, @Nullable Object[] queryValues
) {
if (queryNames.length != queryValues.length) {
throw new RuntimeException("queryNames are not match with queryValues");
}
for (int i = 0; i < queryNames.length; i++) {
addCondition(queryNames[i], queryValues[i]);
}
return getThis();
}
@Override
public B addNotNullCondition(@NotNull String queryName) {
return addCondition("`" + queryName + "` IS NOT NULL");
}
@Override
public B addNotNullCondition(@NotNull String queryName) {
return addCondition("`" + queryName + "` IS NOT NULL");
}
@Override
public B addTimeCondition(
@NotNull String queryName, @Nullable Date startDate, @Nullable Date endDate
) {
if (startDate == null && endDate == null) return getThis(); // 都不限定时间,不用判断了
if (startDate != null) {
addCondition("`" + queryName + "` 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(queryName, "<=", endDate);
}
return getThis();
}
@Override
public B addTimeCondition(
@NotNull String queryName, @Nullable Date startDate, @Nullable Date endDate
) {
if (startDate == null && endDate == null) return getThis(); // 都不限定时间,不用判断了
if (startDate != null) {
addCondition("`" + queryName + "` 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(queryName, "<=", endDate);
}
return getThis();
}
@Override
public B setLimit(int limit) {
this.limit = limit;
return getThis();
}
@Override
public B setLimit(int limit) {
this.limit = limit;
return getThis();
}
protected String buildConditionSQL() {
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(" ");
}
return conditionBuilder.toString();
} else {
return null;
}
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(" ");
}
return conditionBuilder.toString();
} else {
return null;
}
}
}
protected String buildLimitSQL() {
return limit > 0 ? "LIMIT " + limit : "";
}
protected String buildLimitSQL() {
return limit > 0 ? "LIMIT " + limit : "";
}
protected ArrayList<Object> getConditionParams() {
return conditionParams;
}
protected ArrayList<Object> getConditionParams() {
return conditionParams;
}
protected boolean hasConditions() {
return this.conditionSQLs != null && !this.conditionSQLs.isEmpty();
}
protected boolean hasConditions() {
return this.conditionSQLs != null && !this.conditionSQLs.isEmpty();
}
protected boolean hasConditionParams() {
return hasConditions() && getConditionParams() != null && !getConditionParams().isEmpty();
}
protected boolean hasConditionParams() {
return hasConditions() && getConditionParams() != null && !getConditionParams().isEmpty();
}
}
@@ -1,47 +1,48 @@
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;
public class DeleteBuilderImpl
extends AbstractConditionalBuilder<DeleteBuilder, PreparedSQLUpdateAction>
implements DeleteBuilder {
extends AbstractConditionalBuilder<DeleteBuilder, SQLAction<Integer>>
implements DeleteBuilder {
String tableName;
String tableName;
public DeleteBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
}
public DeleteBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
}
@Override
public PreparedSQLUpdateAction build() {
@Override
public PreparedSQLUpdateAction build() {
StringBuilder sqlBuilder = new StringBuilder();
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("DELETE FROM `").append(getTableName()).append("`");
sqlBuilder.append("DELETE FROM `").append(getTableName()).append("`");
if (hasConditions()) sqlBuilder.append(" ").append(buildConditionSQL());
if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL());
if (hasConditions()) sqlBuilder.append(" ").append(buildConditionSQL());
if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL());
return new PreparedSQLUpdateActionImpl(
getManager(), sqlBuilder.toString(),
hasConditionParams() ? getConditionParams() : null
);
}
return new PreparedSQLUpdateActionImpl(
getManager(), sqlBuilder.toString(),
hasConditionParams() ? getConditionParams() : null
);
}
@Override
public String getTableName() {
return tableName;
}
@Override
public String getTableName() {
return tableName;
}
@Override
protected DeleteBuilderImpl getThis() {
return this;
}
@Override
protected DeleteBuilderImpl getThis() {
return this;
}
}
@@ -1,5 +1,6 @@
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;
@@ -8,39 +9,41 @@ import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.List;
public abstract class InsertBuilderImpl<T> extends AbstractSQLBuilder implements InsertBuilder<T> {
public abstract class InsertBuilderImpl<T extends SQLAction<?>>
extends AbstractSQLBuilder implements InsertBuilder<T> {
String tableName;
String tableName;
public InsertBuilderImpl(@NotNull SQLManagerImpl manager, String tableName) {
super(manager);
this.tableName = tableName;
}
public InsertBuilderImpl(@NotNull SQLManagerImpl manager, String tableName) {
super(manager);
this.tableName = tableName;
}
protected static String buildSQL(String tableName, List<String> columnNames) {
int valueLength = columnNames.size();
StringBuilder sqlBuilder = new StringBuilder();
protected static String buildSQL(String tableName, List<String> columnNames) {
int valueLength = columnNames.size();
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("INSERT IGNORE INTO `").append(tableName).append("`(");
Iterator<String> iterator = columnNames.iterator();
while (iterator.hasNext()) {
sqlBuilder.append("`").append(iterator.next()).append("`");
if (iterator.hasNext()) sqlBuilder.append(", ");
}
sqlBuilder.append("INSERT IGNORE INTO `").append(tableName).append("`(");
Iterator<String> iterator = columnNames.iterator();
while (iterator.hasNext()) {
sqlBuilder.append("`").append(iterator.next()).append("`");
if (iterator.hasNext()) sqlBuilder.append(", ");
}
sqlBuilder.append(") VALUES (");
sqlBuilder.append(") VALUES (");
for (int i = 0; i < valueLength; i++) {
sqlBuilder.append("?");
if (i != valueLength - 1) {
sqlBuilder.append(", ");
}
}
sqlBuilder.append(")");
return sqlBuilder.toString();
}
for (int i = 0; i < valueLength; i++) {
sqlBuilder.append("?");
if (i != valueLength - 1) {
sqlBuilder.append(", ");
}
}
sqlBuilder.append(")");
return sqlBuilder.toString();
}
public String getTableName() {
return tableName;
}
@Override
public String getTableName() {
return tableName;
}
}
@@ -1,5 +1,6 @@
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;
@@ -8,39 +9,41 @@ import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.List;
public abstract class ReplaceBuilderImpl<T> extends AbstractSQLBuilder implements ReplaceBuilder<T> {
public abstract class ReplaceBuilderImpl<T extends SQLAction<?>>
extends AbstractSQLBuilder implements ReplaceBuilder<T> {
String tableName;
String tableName;
public ReplaceBuilderImpl(@NotNull SQLManagerImpl manager, String tableName) {
super(manager);
this.tableName = tableName;
}
public ReplaceBuilderImpl(@NotNull SQLManagerImpl manager, String tableName) {
super(manager);
this.tableName = tableName;
}
protected static String buildSQL(String tableName, List<String> columnNames) {
int valueLength = columnNames.size();
StringBuilder sqlBuilder = new StringBuilder();
protected static String buildSQL(String tableName, List<String> columnNames) {
int valueLength = columnNames.size();
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("REPLACE INTO `").append(tableName).append("`(");
Iterator<String> iterator = columnNames.iterator();
while (iterator.hasNext()) {
sqlBuilder.append("`").append(iterator.next()).append("`");
if (iterator.hasNext()) sqlBuilder.append(", ");
}
sqlBuilder.append("REPLACE INTO `").append(tableName).append("`(");
Iterator<String> iterator = columnNames.iterator();
while (iterator.hasNext()) {
sqlBuilder.append("`").append(iterator.next()).append("`");
if (iterator.hasNext()) sqlBuilder.append(", ");
}
sqlBuilder.append(") VALUES (");
sqlBuilder.append(") VALUES (");
for (int i = 0; i < valueLength; i++) {
sqlBuilder.append("?");
if (i != valueLength - 1) {
sqlBuilder.append(", ");
}
}
sqlBuilder.append(")");
return sqlBuilder.toString();
}
for (int i = 0; i < valueLength; i++) {
sqlBuilder.append("?");
if (i != valueLength - 1) {
sqlBuilder.append(", ");
}
}
sqlBuilder.append(")");
return sqlBuilder.toString();
}
public String getTableName() {
return tableName;
}
@Override
public String getTableName() {
return tableName;
}
}
@@ -0,0 +1,120 @@
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.TableAlertBuilder;
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;
public class TableAlterBuilderImpl extends AbstractSQLBuilder implements TableAlertBuilder {
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) {
return new SQLUpdateActionImpl(getManager(),
"ALERT TABLE `" + getTableName() + "` RENAME TO `" + newTableName + "`"
);
}
@Override
public SQLAction<Integer> changeComment(@NotNull String newTableComment) {
return new SQLUpdateActionImpl(getManager(),
"ALERT TABLE `" + getTableName() + "` COMMENT '" + newTableComment + "'"
);
}
@Override
public SQLAction<Integer> setAutoIncrementIndex(int index) {
return new SQLUpdateActionImpl(getManager(),
"ALERT TABLE `" + getTableName() + "` AUTO_INCREMENT=" + index
);
}
@Override
public SQLAction<Integer> addIndex(@NotNull IndexType indexType, @NotNull String indexName, @NotNull String columnName, @NotNull String... moreColumns) {
return createAction(
"ALERT TABLE `" + getTableName() + "` ADD "
+ TableCreateBuilderImpl.buildIndexSettings(indexType, indexName, columnName, moreColumns)
);
}
@Override
public SQLAction<Integer> dropIndex(@NotNull String indexName) {
return createAction(
"ALERT TABLE `" + getTableName() + "` DROP INDEX `" + indexName + "`"
);
}
@Override
public SQLAction<Integer> dropForeignKey(@NotNull String keySymbol) {
return createAction(
"ALERT TABLE `" + getTableName() + "` DROP FOREIGN KEY `" + keySymbol + "`"
);
}
@Override
public SQLAction<Integer> dropPrimaryKey() {
return createAction(
"ALERT TABLE `" + getTableName() + "` DROP PRIMARY KEY"
);
}
@Override
public SQLAction<Integer> addColumn(@NotNull String columnName, @NotNull String settings, @Nullable String afterColumn) {
return createAction(
"ALERT TABLE `" + getTableName() + "` ADD `" + columnName + "` " + settings
);
}
@Override
public SQLAction<Integer> renameColumn(@NotNull String columnName, @NotNull String newName) {
return createAction(
"ALERT TABLE `" + getTableName() + "` RENAME COLUMN `" + columnName + "` TO `" + newName + "`"
);
}
@Override
public SQLAction<Integer> modifyColumn(@NotNull String columnName, @NotNull String settings) {
return createAction(
"ALERT TABLE `" + getTableName() + "` MODIFY COLUMN `" + columnName + "` " + settings
);
}
@Override
public SQLAction<Integer> removeColumn(@NotNull String columnName) {
return createAction(
"ALERT TABLE `" + getTableName() + "` DROP `" + columnName + "`"
);
}
@Override
public SQLAction<Integer> setColumnDefault(@NotNull String columnName, @NotNull String defaultValue) {
return createAction(
"ALERT TABLE `" + getTableName() + "` ALERT `" + columnName + "` SET DEFAULT " + defaultValue
);
}
@Override
public SQLAction<Integer> removeColumnDefault(@NotNull String columnName) {
return createAction(
"ALERT TABLE `" + getTableName() + "` ALERT `" + columnName + "` DROP DEFAULT"
);
}
private SQLUpdateActionImpl createAction(@NotNull String sql) {
return new SQLUpdateActionImpl(getManager(), sql);
}
}
@@ -3,9 +3,12 @@ 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.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;
@@ -13,59 +16,138 @@ import java.util.List;
public class TableCreateBuilderImpl extends AbstractSQLBuilder implements TableCreateBuilder {
String tableName;
protected final @NotNull String tableName;
List<String> columns;
@NotNull List<String> columns = new ArrayList<>();
@NotNull List<String> indexes = new ArrayList<>();
@NotNull List<String> foreignKeys = new ArrayList<>();
String tableSettings;
@NotNull String tableSettings = defaultTablesSettings();
@Nullable String tableComment;
public TableCreateBuilderImpl(SQLManagerImpl manager, String tableName) {
super(manager);
this.tableName = tableName;
this.columns = new ArrayList<>();
defaultTablesSettings();
}
public TableCreateBuilderImpl(SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
}
@Override
public @NotNull String getTableName() {
return this.tableName;
}
@Override
public @NotNull String getTableName() {
return this.tableName;
}
@Override
public @NotNull String getTableSettings() {
return this.tableSettings;
}
@Override
public @NotNull String getTableSettings() {
return this.tableSettings;
}
@Override
public SQLUpdateAction build() {
StringBuilder createSQL = new StringBuilder();
createSQL.append("CREATE TABLE IF NOT EXISTS `").append(tableName).append("`");
createSQL.append("(");
for (int i = 0; i < columns.size(); i++) {
createSQL.append(columns.get(i));
if (i != columns.size() - 1) createSQL.append(", ");
}
createSQL.append(") ").append(tableSettings);
@Override
public SQLUpdateAction build() {
StringBuilder createSQL = new StringBuilder();
createSQL.append("CREATE TABLE IF NOT EXISTS `").append(tableName).append("`");
createSQL.append("(");
for (int i = 0; i < columns.size(); i++) {
createSQL.append(columns.get(i));
if (i != columns.size() - 1) createSQL.append(", ");
}
return new SQLUpdateActionImpl(getManager(), createSQL.toString());
}
for (int i = 0; i < indexes.size(); i++) {
createSQL.append(indexes.get(i));
if (i != indexes.size() - 1) createSQL.append(", ");
}
@Override
public TableCreateBuilder addColumn(@NotNull String column) {
this.columns.add(column);
return this;
}
for (int i = 0; i < foreignKeys.size(); i++) {
createSQL.append(foreignKeys.get(i));
if (i != foreignKeys.size() - 1) createSQL.append(", ");
}
@Override
public TableCreateBuilder setColumns(@NotNull String[] columns) {
this.columns = Arrays.asList(columns);
return this;
}
createSQL.append(") ").append(getTableSettings());
@Override
public TableCreateBuilder setTableSettings(@NotNull String settings) {
this.tableSettings = settings;
return this;
}
if (tableComment != null) {
createSQL.append(" COMMENT '").append(tableComment).append("'");
}
return new SQLUpdateActionImpl(getManager(), createSQL.toString());
}
@Override
public TableCreateBuilder addColumn(@NotNull String column) {
this.columns.add(column);
return this;
}
@Override
public TableCreateBuilder setIndex(@NotNull IndexType type, @Nullable String indexName,
@NotNull String columnName, @NotNull String... moreColumns) {
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) {
StringBuilder keyBuilder = new StringBuilder();
keyBuilder.append("CONSTRAINT ");
if (constraintName == null) {
keyBuilder.append("`").append("fk_").append(tableColumn).append("_").append(foreignTable).append("`");
} else {
keyBuilder.append("`").append(constraintName).append("`");
}
keyBuilder.append(" ");
keyBuilder.append("FOREIGN KEY (`").append(tableColumn).append("`) ");
keyBuilder.append("REFERENCES `").append(foreignTable).append("`(`").append(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) {
this.columns = Arrays.asList(columns);
return this;
}
@Override
public TableCreateBuilder setTableSettings(@NotNull String settings) {
this.tableSettings = settings;
return this;
}
@Override
public TableCreateBuilder setTableComment(@Nullable String comment) {
this.tableComment = comment;
return this;
}
protected static String buildIndexSettings(@NotNull IndexType indexType, @Nullable String indexName,
@NotNull String columnName, @NotNull String... moreColumns) {
StringBuilder indexBuilder = new StringBuilder();
indexBuilder.append(indexType.getName()).append(" ");
if (indexName != null) {
indexBuilder.append("`").append(indexName).append("`");
}
indexBuilder.append("(");
indexBuilder.append("`").append(columnName).append("`");
if (moreColumns.length > 0) {
indexBuilder.append(", ");
for (int i = 0; i < moreColumns.length; i++) {
indexBuilder.append(moreColumns[i]);
if (i != moreColumns.length - 1) indexBuilder.append(", ");
}
}
indexBuilder.append(")");
return indexBuilder.toString();
}
}
@@ -1,6 +1,7 @@
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;
@@ -9,72 +10,72 @@ import org.jetbrains.annotations.NotNull;
import java.util.*;
public class UpdateBuilderImpl
extends AbstractConditionalBuilder<UpdateBuilder, PreparedSQLUpdateAction>
implements UpdateBuilder {
extends AbstractConditionalBuilder<UpdateBuilder, SQLAction<Integer>>
implements UpdateBuilder {
String tableName;
String tableName;
List<String> columnNames;
List<Object> columnValues;
List<String> columnNames;
List<Object> columnValues;
public UpdateBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
}
public UpdateBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
}
@Override
public PreparedSQLUpdateAction build() {
@Override
public PreparedSQLUpdateAction build() {
StringBuilder sqlBuilder = new StringBuilder();
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("UPDATE `").append(getTableName()).append("` SET ");
sqlBuilder.append("UPDATE `").append(getTableName()).append("` SET ");
Iterator<String> iterator = this.columnNames.iterator();
while (iterator.hasNext()) {
sqlBuilder.append("`").append(iterator.next()).append("` = ?");
if (iterator.hasNext()) sqlBuilder.append(" , ");
}
List<Object> allParams = new ArrayList<>(this.columnValues);
Iterator<String> iterator = this.columnNames.iterator();
while (iterator.hasNext()) {
sqlBuilder.append("`").append(iterator.next()).append("` = ?");
if (iterator.hasNext()) sqlBuilder.append(" , ");
}
List<Object> allParams = new ArrayList<>(this.columnValues);
if (hasConditions()) {
sqlBuilder.append(" ").append(buildConditionSQL());
allParams.addAll(getConditionParams());
}
if (hasConditions()) {
sqlBuilder.append(" ").append(buildConditionSQL());
allParams.addAll(getConditionParams());
}
if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL());
if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL());
return new PreparedSQLUpdateActionImpl(getManager(), sqlBuilder.toString(), allParams);
}
return new PreparedSQLUpdateActionImpl(getManager(), sqlBuilder.toString(), allParams);
}
@Override
public String getTableName() {
return tableName;
}
@Override
public String getTableName() {
return tableName;
}
@Override
public UpdateBuilder setColumnValues(LinkedHashMap<String, Object> columnData) {
this.columnNames = new ArrayList<>();
this.columnValues = new ArrayList<>();
columnData.forEach((name, value) -> {
this.columnNames.add(name);
this.columnValues.add(value);
});
return this;
}
@Override
public UpdateBuilder setColumnValues(LinkedHashMap<String, Object> columnData) {
this.columnNames = new ArrayList<>();
this.columnValues = new ArrayList<>();
columnData.forEach((name, value) -> {
this.columnNames.add(name);
this.columnValues.add(value);
});
return this;
}
@Override
public UpdateBuilder setColumnValues(String[] columnNames, Object[] columnValues) {
if (columnNames.length != columnValues.length) {
throw new RuntimeException("columnNames are not match with columnValues");
}
this.columnNames = Arrays.asList(columnNames);
this.columnValues = Arrays.asList(columnValues);
return this;
}
@Override
public UpdateBuilder setColumnValues(String[] columnNames, Object[] columnValues) {
if (columnNames.length != columnValues.length) {
throw new RuntimeException("columnNames are not match with columnValues");
}
this.columnNames = Arrays.asList(columnNames);
this.columnValues = Arrays.asList(columnValues);
return this;
}
@Override
protected UpdateBuilder getThis() {
return this;
}
@Override
protected UpdateBuilder getThis() {
return this;
}
}
@@ -129,6 +129,11 @@ public class SQLManagerImpl implements SQLManager {
return new TableCreateBuilderImpl(this, tableName);
}
@Override
public TableAlertBuilder alterTable(@NotNull String tableName) {
return new TableAlterBuilderImpl(this, tableName);
}
@Override
public QueryBuilder createQuery() {
return new QueryBuilderImpl(this);
@@ -25,7 +25,15 @@ public class SQLQueryImpl implements SQLQuery {
SQLManagerImpl sqlManager, QueryActionImpl queryAction,
Connection connection, Statement statement, ResultSet resultSet
) {
this.executeTime = System.currentTimeMillis();
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;
@@ -10,195 +10,199 @@ 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 "?"所代表的对应参数列表
* @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 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 "?"所代表的对应参数列表
* @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 {
/**
* 创建批量操作的一个 {@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();
}
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;
}
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参数
* @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;// 无参数
}
/**
* 填充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;
}
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) {
int sqlType = Types.VARCHAR;
/**
* 获取null字段对应位置的数据类型
* 如果类型获取失败将使用默认的 {@link Types#VARCHAR}
*
* @param statement {@link PreparedStatement}
* @param paramIndex 参数序列,第一位从1开始
* @return 数据类型,默认为 {@link Types#VARCHAR}
*/
public static int getNullType(PreparedStatement statement, int paramIndex) {
int sqlType = Types.VARCHAR;
final ParameterMetaData pmd;
try {
pmd = statement.getParameterMetaData();
sqlType = pmd.getParameterType(paramIndex);
} catch (SQLException ignore) {
}
final ParameterMetaData pmd;
try {
pmd = statement.getParameterMetaData();
sqlType = pmd.getParameterType(paramIndex);
} catch (SQLException ignore) {
}
return sqlType;
}
return sqlType;
}
/**
* 为 {@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 {
/**
* 为 {@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);
}
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;
}
// 针对UUID特殊处理,避免元数据直接
if (param instanceof UUID) {
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;
}
// 针对StringBuilder或StringBuffer进行处理,避免元数据传入
if (param instanceof StringBuilder || param instanceof StringBuffer) {
preparedStatement.setString(paramIndex, param.toString());
return;
}
// 针对大数字类型的特殊处理
if (param instanceof Number) {
if (param instanceof BigDecimal) {
// BigDecimal的转换交给JDBC驱动处理
preparedStatement.setBigDecimal(paramIndex, (BigDecimal) param);
return;
}
if (param instanceof BigInteger) {
// BigInteger转为BigDecimal
preparedStatement.setBigDecimal(paramIndex, new BigDecimal((BigInteger) param));
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;
}
// 其它参数类型直接插入
preparedStatement.setObject(paramIndex, param);
}
// 针对大数字类型的特殊处理
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;
}
// 其它数字类型按照默认类型传入
}
// 其它参数类型直接传入
preparedStatement.setObject(paramIndex, param);
}
}