1
mirror of https://github.com/CarmJos/EasySQL.git synced 2024-09-19 21:35:47 +00:00

[v0.3.0] 版本更新

- [A] 添加 TableAlertBuilder 用于快捷修改表的相关设定
- [A] 为 TableCreateBuilder 添加数个方法,包含创建索引、自增主键与外键。
- [R] 修改部分Builder的参数值,为泛型添加限定。
This commit is contained in:
Carm Jos 2022-01-25 23:18:05 +08:00
parent d29d06053c
commit cf91a10b6d
39 changed files with 1454 additions and 645 deletions

View File

@ -11,7 +11,8 @@ on:
types: [ published ]
jobs:
deploy:
gh-deploy:
name: "Publish Project (GitHub)"
runs-on: ubuntu-latest
steps:
@ -27,7 +28,7 @@ jobs:
server-password: MAVEN_TOKEN
- name: "Maven Deploy With Javadoc"
run: mvn -B deploy --file pom.xml -DskipTests
run: mvn -B -Pgithub deploy --file pom.xml -DskipTests
env:
MAVEN_USERNAME: ${{ github.repository_owner }}
MAVEN_TOKEN: ${{secrets.GITHUB_TOKEN}}
@ -77,3 +78,28 @@ jobs:
run: |
cd docs
git push origin HEAD:gh-pages --force
central-deploy:
name: "Deploy Project (Central Repository)"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: "Set up JDK"
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'adopt'
cache: maven
server-id: ossrh
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: "Central Deploy"
run: mvn -B -Possrh deploy --file pom.xml -DskipTests
env:
MAVEN_USERNAME: ${{ secrets.OSSRH_USER }}
MAVEN_PASSWORD: ${{ secrets.OSSRH_PASS }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

View File

@ -5,10 +5,17 @@
<parent>
<groupId>cc.carm.lib</groupId>
<artifactId>easysql-parent</artifactId>
<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-api</artifactId>
<packaging>jar</packaging>
@ -45,13 +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>
</properties>
<build>
<plugins>
<plugin>

View File

@ -3,13 +3,14 @@ package cc.carm.lib.easysql.api;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import cc.carm.lib.easysql.api.function.SQLFunction;
import cc.carm.lib.easysql.api.function.SQLHandler;
import cc.carm.lib.easysql.api.function.impl.DefaultSQLExceptionHandler;
import cc.carm.lib.easysql.api.function.defaults.DefaultSQLExceptionHandler;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.UUID;
import java.util.logging.Logger;
/**
* SQLAction 是用于承载SQL语句并进行处理返回的基本类
@ -188,7 +189,10 @@ public interface SQLAction<T> {
}
/**
* @return 默认的异常处理器
* 默认的异常处理器
*
* @return {@link DefaultSQLExceptionHandler#get(Logger)}
* @see DefaultSQLExceptionHandler
*/
default SQLExceptionHandler defaultExceptionHandler() {
return DefaultSQLExceptionHandler.get(getManager().getLogger());

View File

@ -28,7 +28,7 @@ public interface SQLManager {
default void setDebugMode(boolean enable) {
setDebugMode(() -> enable);
}
/**
* 得到连接池源
*
@ -109,6 +109,14 @@ public interface SQLManager {
*/
TableCreateBuilder createTable(@NotNull String tableName);
/**
* 对库中的某个表执行更改
*
* @param tableName 表名
* @return {@link TableAlertBuilder}
*/
TableAlertBuilder alterTable(@NotNull String tableName);
/**
* 新建一个查询
*

View File

@ -1,6 +1,5 @@
package cc.carm.lib.easysql.api;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.action.query.PreparedQueryAction;
import cc.carm.lib.easysql.api.action.query.QueryAction;
@ -10,43 +9,44 @@ import java.sql.Statement;
public interface SQLQuery extends AutoCloseable {
/**
* 获取该查询创建的时间
*
* @return 创建时间
*/
long getExecuteTime();
/**
* 获取该查询创建的时间
*
* @return 创建时间
*/
long getExecuteTime();
/**
* 得到承载该SQLQuery的对应{@link SQLManager}
*
* @return {@link SQLManager}
*/
SQLManager getManager();
/**
* 得到承载该SQLQuery的对应{@link SQLManager}
*
* @return {@link SQLManager}
*/
SQLManager getManager();
/**
* 得到承载该SQLQuery的对应{@link QueryAction}
*
* @return {@link QueryAction} {@link PreparedQueryAction}
*/
QueryAction getAction();
/**
* 得到承载该SQLQuery的对应{@link QueryAction}
*
* @return {@link QueryAction} {@link PreparedQueryAction}
*/
QueryAction getAction();
ResultSet getResultSet();
ResultSet getResultSet();
/**
* 得到设定的SQL语句
*
* @return SQL语句
*/
String getSQLContent();
/**
* 得到设定的SQL语句
*
* @return SQL语句
*/
String getSQLContent();
/**
* 关闭所有内容
*/
void close();
/**
* 关闭所有内容
*/
@Override
void close();
Statement getStatement();
Statement getStatement();
Connection getConnection();
Connection getConnection();
}

View File

@ -1,7 +1,6 @@
package cc.carm.lib.easysql.api.action;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@ -22,18 +21,4 @@ public interface SQLUpdateBatchAction extends SQLAction<List<Integer>> {
List<String> getSQLContents();
@Override
default SQLExceptionHandler defaultExceptionHandler() {
return (exception, action) -> {
getManager().getLogger().severe("Error when execute SQLs : ");
int i = 1;
for (String content : getSQLContents()) {
getManager().getLogger().severe("#" + i + " [" + content + "]");
i++;
}
getManager().getLogger().severe(exception.getLocalizedMessage());
exception.printStackTrace();
};
}
}

View File

@ -1,5 +1,6 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.SQLBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -7,36 +8,47 @@ import org.jetbrains.annotations.Nullable;
import java.util.Date;
import java.util.LinkedHashMap;
public interface ConditionalBuilder<B extends ConditionalBuilder<B, T>, T> extends SQLBuilder {
public interface ConditionalBuilder<B extends ConditionalBuilder<B, T>, T extends SQLAction<?>> extends SQLBuilder {
T build();
/**
* 将现有条件构建完整的SQL语句用于执行
*
* @return {@link cc.carm.lib.easysql.api.SQLAction}
*/
T build();
B setLimit(int limit);
/**
* 设定取出的条数
*
* @param limit 条数限制
* @return {@link B}
*/
B setLimit(int limit);
B setConditions(@Nullable String condition);
B setConditions(@Nullable String condition);
B setConditions(LinkedHashMap<@NotNull String, @Nullable Object> conditionSQLs);
B setConditions(LinkedHashMap<@NotNull String, @Nullable Object> conditionSQLs);
B addCondition(@Nullable String condition);
B addCondition(@Nullable String condition);
B addCondition(@NotNull String queryName, @NotNull String operator, @Nullable Object queryValue);
B addCondition(@NotNull String queryName, @NotNull String operator, @Nullable Object queryValue);
default B addCondition(@NotNull String queryName, @Nullable Object queryValue) {
return addCondition(queryName, "=", queryValue);
}
default B addCondition(@NotNull String queryName, @Nullable Object queryValue) {
return addCondition(queryName, "=", queryValue);
}
B addCondition(@NotNull String[] queryNames, @Nullable Object[] queryValues);
B addCondition(@NotNull String[] queryNames, @Nullable Object[] queryValues);
B addNotNullCondition(@NotNull String queryName);
B addNotNullCondition(@NotNull String queryName);
default B addTimeCondition(@NotNull String queryName, long startMillis, long endMillis) {
return addTimeCondition(queryName,
startMillis > 0 ? new Date(startMillis) : null,
endMillis > 0 ? new Date(endMillis) : null
);
}
default B addTimeCondition(@NotNull String queryName, long startMillis, long endMillis) {
return addTimeCondition(queryName,
startMillis > 0 ? new Date(startMillis) : null,
endMillis > 0 ? new Date(endMillis) : null
);
}
B addTimeCondition(@NotNull String queryName, @Nullable java.util.Date startDate, @Nullable java.util.Date endDate);
B addTimeCondition(@NotNull String queryName, @Nullable java.util.Date startDate, @Nullable java.util.Date endDate);
}

View File

@ -1,9 +1,9 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.SQLAction;
public interface DeleteBuilder extends ConditionalBuilder<DeleteBuilder, PreparedSQLUpdateAction> {
public interface DeleteBuilder extends ConditionalBuilder<DeleteBuilder, SQLAction<Integer>> {
String getTableName();
String getTableName();
}

View File

@ -1,9 +1,11 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLAction;
import java.util.Arrays;
import java.util.List;
public interface InsertBuilder<T> {
public interface InsertBuilder<T extends SQLAction<?>> {
String getTableName();

View File

@ -1,17 +1,25 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLAction;
import java.util.Arrays;
import java.util.List;
public interface ReplaceBuilder<T> {
/**
* REPLACE 语句用于将一组值更新进数据表中
* <br> 执行后将通过表中键判断该数据是否存在若存在则用新数据替换原来的值若不存在则会插入该数据
* <br> 在使用REPLACE时表与所给行列数据中必须包含唯一索引(或主键)且索引不得为空值否则将等同于插入语句
*
* @param <T> 最终构建出的 {@link SQLAction} 类型
*/
public interface ReplaceBuilder<T extends SQLAction<?>> {
String getTableName();
String getTableName();
T setColumnNames(List<String> columnNames);
default T setColumnNames(String... columnNames) {
return setColumnNames(columnNames == null ? null : Arrays.asList(columnNames));
}
T setColumnNames(List<String> columnNames);
default T setColumnNames(String... columnNames) {
return setColumnNames(columnNames == null ? null : Arrays.asList(columnNames));
}
}

View File

@ -1,6 +1,129 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.SQLBuilder;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.api.enums.IndexType;
import cc.carm.lib.easysql.api.enums.NumberType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface TableAlertBuilder extends SQLBuilder {
SQLAction<Integer> renameTo(@NotNull String newTableName);
SQLAction<Integer> changeComment(@NotNull String newTableComment);
SQLAction<Integer> setAutoIncrementIndex(int index);
SQLAction<Integer> addIndex(@NotNull IndexType indexType, @NotNull String indexName,
@NotNull String columnName, @NotNull String... moreColumns);
/**
* 为该表移除一个索引
*
* @param indexName 索引名
* @return @return {@link SQLUpdateAction}
*/
SQLAction<Integer> dropIndex(@NotNull String indexName);
/**
* 为该表移除一个外键
*
* @param keySymbol 外键名
* @return @return {@link SQLUpdateAction}
*/
SQLAction<Integer> dropForeignKey(@NotNull String keySymbol);
/**
* 为该表移除主键(须添加新主键)
*
* @return @return {@link SQLUpdateAction}
*/
SQLAction<Integer> dropPrimaryKey();
/**
* 为表添加一列
*
* @param columnName 列名
* @param settings 列的相关设定
* @return {@link SQLUpdateAction}
*/
default SQLAction<Integer> addColumn(@NotNull String columnName, @NotNull String settings) {
return addColumn(columnName, settings, null);
}
/**
* 为表添加一列
*
* @param columnName 列名
* @param settings 列的相关设定
* @param afterColumn 该列增添到哪个列的后面
* <p> 该参数若省缺则放于最后一行
* <p> 若为 "" 则置于首行
* @return {@link SQLUpdateAction}
*/
SQLAction<Integer> addColumn(@NotNull String columnName, @NotNull String settings, @Nullable String afterColumn);
SQLAction<Integer> renameColumn(@NotNull String columnName, @NotNull String newName);
SQLAction<Integer> modifyColumn(@NotNull String columnName, @NotNull String settings);
default SQLAction<Integer> modifyColumn(@NotNull String columnName, @NotNull String columnSettings, @NotNull String afterColumn) {
return modifyColumn(columnName, columnSettings + " AFTER `" + afterColumn + "`");
}
SQLAction<Integer> removeColumn(@NotNull String columnName);
SQLAction<Integer> setColumnDefault(@NotNull String columnName, @NotNull String defaultValue);
SQLAction<Integer> removeColumnDefault(@NotNull String columnName);
/**
* 为该表添加一个自增列
* <p> 自增列强制要求为数字类型非空且为UNIQUE
* <p> 注意一个表只允许有一个自增列
*
* @param columnName 列名
* @param numberType 数字类型若省缺则为 {@link NumberType#INT}
* @param primary 是否为主键若否则只为唯一键
* @param unsigned 是否采用 UNSIGNED (即无负数可以增加自增键的最高数建议为true)
* @return {@link TableCreateBuilder}
*/
default SQLAction<Integer> addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType,
boolean primary, boolean unsigned) {
return addColumn(columnName,
(numberType == null ? NumberType.INT : numberType).name()
+ (unsigned ? " UNSIGNED " : " ")
+ "NOT NULL AUTO_INCREMENT " + (primary ? "PRIMARY KEY" : "UNIQUE KEY"),
""
);
}
/**
* 为该表添加一个自增列
* <br> 自增列强制要求为数字类型非空且为UNIQUE
* <p> 注意一个表只允许有一个自增列
*
* @param columnName 列名
* @param numberType 数字类型若省缺则为 {@link NumberType#INT}
* @return {@link TableAlertBuilder}
*/
default SQLAction<Integer> addAutoIncrementColumn(@NotNull String columnName, @NotNull NumberType numberType) {
return addAutoIncrementColumn(columnName, numberType, false, true);
}
/**
* 为该表添加一个自增列
* <br> 自增列强制要求为数字类型非空且为UNIQUE
* <p> 注意一个表只允许有一个自增列
*
* @param columnName 列名
* @return {@link TableAlertBuilder}
*/
default SQLAction<Integer> addAutoIncrementColumn(@NotNull String columnName) {
return addAutoIncrementColumn(columnName, NumberType.INT);
}
}

View File

@ -2,29 +2,239 @@ package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLBuilder;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface TableCreateBuilder extends SQLBuilder {
@NotNull String getTableName();
/**
* 将现有条件构建完整的SQL语句用于执行
*
* @return {@link SQLUpdateAction}
*/
SQLUpdateAction build();
@NotNull String getTableSettings();
@NotNull String getTableName();
TableCreateBuilder setTableSettings(@NotNull String settings);
/**
* 得到表的设定
* <p> 若未使用 {@link #setTableSettings(String)} 方法则会采用 {@link #defaultTablesSettings()}
*
* @return TableSettings
*/
@NotNull String getTableSettings();
SQLUpdateAction build();
TableCreateBuilder setTableSettings(@NotNull String settings);
default TableCreateBuilder addColumn(@NotNull String columnName, @NotNull String settings) {
return addColumn("`" + columnName + "` " + settings);
}
/**
* 设定表的标注一般用于解释该表的作用
*
* @param comment 表标注
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder setTableComment(@Nullable String comment);
TableCreateBuilder addColumn(@NotNull String column);
/**
* 直接设定表的所有列信息
*
* @param columns 列的相关信息 (包括列设定)
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder setColumns(@NotNull String... columns);
TableCreateBuilder setColumns(@NotNull String... columns);
/**
* 为该表添加一个列
*
* @param column 列的相关信息
* <br> `uuid` VARCHAR(36) NOT NULL UNIQUE KEY
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder addColumn(@NotNull String column);
default TableCreateBuilder defaultTablesSettings() {
return setTableSettings("ENGINE=InnoDB DEFAULT CHARSET=utf8");
}
/**
* 为该表添加一个列
*
* @param columnName 列名
* @param settings 列的设定
* <br> VARCHAR(36) NOT NULL UNIQUE KEY
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addColumn(@NotNull String columnName, @NotNull String settings) {
return addColumn("`" + columnName + "` " + settings);
}
/**
* 为该表添加一个列
*
* @param columnName 列名
* @param settings 列的设定
* <br> VARCHAR(36) NOT NULL UNIQUE KEY
* @param comments 列的注解用于解释该列数据的作用
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addColumn(@NotNull String columnName, @NotNull String settings, @NotNull String comments) {
return addColumn(columnName, settings + " COMMENT '" + comments + "'");
}
/**
* 为该表添加一个自增列
* <p> 自增列强制要求为数字类型非空且为UNIQUE
* <p> 注意一个表只允许有一个自增列
*
* @param columnName 列名
* @param numberType 数字类型若省缺则为 {@link NumberType#INT}
* @param primary 是否为主键若为false则设定为唯一键
* @param unsigned 是否采用 UNSIGNED (即无负数可以增加自增键的最高数建议为true)
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType,
boolean primary, boolean unsigned) {
return addColumn(columnName,
(numberType == null ? NumberType.INT : numberType).name()
+ (unsigned ? " UNSIGNED " : " ")
+ "NOT NULL AUTO_INCREMENT " + (primary ? "PRIMARY KEY" : "UNIQUE KEY")
);
}
/**
* 为该表添加一个自增主键列
* <p> 自增列强制要求为数字类型非空且为UNIQUE
* <p> 注意一个表只允许有一个自增列
*
* @param columnName 列名
* @param numberType 数字类型若省缺则为 {@link NumberType#INT}
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType) {
return addAutoIncrementColumn(columnName, numberType, true, true);
}
/**
* 为该表添加一个INT类型的自增主键列
* <p> 自增列强制要求为数字类型非空且为UNIQUE
* <p> 本方法采用的类型为 INT 如有其他需要请自行使用 {@link #addAutoIncrementColumn(String, NumberType)} 方法
* <p> 注意一个表只允许有一个自增列
*
* @param columnName 列名
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName) {
return addAutoIncrementColumn(columnName, null);
}
/**
* 设定表中的某列为索引或键
*
* <p>创建索引时你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)
* <br>虽然索引大大提高了查询速度同时却会降低更新表的速度如对表进行INSERTUPDATE 和DELETE
* <br>因此请合理的设计索引
*
* @param type 索引类型
* @param columnName 索引包含的列
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder setIndex(@NotNull IndexType type,
@NotNull String columnName) {
return setIndex(type, null, columnName);
}
/**
* 设定表中的某列为索引或键
*
* <p>创建索引时你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)
* <br>虽然索引大大提高了查询速度同时却会降低更新表的速度如对表进行INSERTUPDATE 和DELETE
* <br>因此请合理的设计索引
*
* @param type 索引类型
* @param indexName 索引名称缺省时将根据第一个索引列赋一个名称
* @param columnName 索引包含的列
* @param moreColumns 联合索引需要包含的列
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder setIndex(@NotNull IndexType type, @Nullable String indexName,
@NotNull String columnName, @NotNull String... moreColumns);
/**
* 以本表位从表为表中某列设定自参照外键(即自参照完整性)
*
* <p>外键约束FOREIGN KEY是表的一个特殊字段经常与主键约束一起使用
* <br>外键用来建立主表与从表的关联关系为两个表的数据建立连接约束两个表中数据的一致性和完整性
* <br>主表删除某条记录时从表中与之对应的记录也必须有相应的改变
*
* @param tableColumn 本表中的列
* @param foreignColumn 外键关联表中对应的关联列必须为目标表的主键 {@link IndexType#PRIMARY_KEY}
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addForeignKey(@NotNull String tableColumn, @NotNull String foreignColumn) {
return addForeignKey(tableColumn, getTableName(), foreignColumn);
}
/**
* 以本表位从表为表中某列设定外键
*
* <p>外键约束FOREIGN KEY是表的一个特殊字段经常与主键约束一起使用
* <br>外键用来建立主表与从表的关联关系为两个表的数据建立连接约束两个表中数据的一致性和完整性
* <br>主表删除某条记录时从表中与之对应的记录也必须有相应的改变
*
* @param tableColumn 本表中的列
* @param foreignTable 外键关联主表必须为已存在的表或本表且必须有主键
* @param foreignColumn 外键关联主表中对应的关联列须满足
* <p> 1. 为主表的主键 {@link IndexType#PRIMARY_KEY}
* <p> 2. 数据类型必须和所要建立主键的列的数据类型相同
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addForeignKey(@NotNull String tableColumn,
@NotNull String foreignTable, @NotNull String foreignColumn) {
return addForeignKey(tableColumn, null, foreignTable, foreignColumn);
}
/**
* 以本表位从表为表中某列设定外键
*
* <p>外键约束FOREIGN KEY是表的一个特殊字段经常与主键约束一起使用
* <br>外键用来建立主表与从表的关联关系为两个表的数据建立连接约束两个表中数据的一致性和完整性
* <br>主表删除某条记录时从表中与之对应的记录也必须有相应的改变
*
* @param tableColumn 本表中的列
* @param constraintName 约束名缺省时将使用参数自动生成 <i>fk_[tableColumn]_[foreignTable]</i>
* @param foreignTable 外键关联主表必须为已存在的表或本表且必须有主键
* @param foreignColumn 外键关联主表中对应的关联列须满足
* <p> 1. 为主表的主键 {@link IndexType#PRIMARY_KEY}
* <p> 2. 数据类型必须和所要建立主键的列的数据类型相同
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addForeignKey(@NotNull String tableColumn, @Nullable String constraintName,
@NotNull String foreignTable, @NotNull String foreignColumn) {
return addForeignKey(tableColumn, constraintName, foreignTable, foreignColumn, null, null);
}
/**
* 以本表位从表为表中某列设定外键
*
* <p>外键约束FOREIGN KEY是表的一个特殊字段经常与主键约束一起使用
* <br>外键用来建立主表与从表的关联关系为两个表的数据建立连接约束两个表中数据的一致性和完整性
* <br>主表删除某条记录时从表中与之对应的记录也必须有相应的改变
*
* @param tableColumn 本表中的列
* @param constraintName 约束名缺省时将使用参数自动生成 <i>fk_[tableColumn]_[foreignTable]</i>
* @param foreignTable 外键关联主表必须为已存在的表或本表且必须有主键
* @param foreignColumn 外键关联主表中对应的关联列须满足
* <p> 1. 为主表的主键 {@link IndexType#PRIMARY_KEY}
* <p> 2. 数据类型必须和所要建立主键的列的数据类型相同
* @param updateRule 在外键被更新时采用的规则缺省时默认为{@link ForeignKeyRule#RESTRICT}
* @param deleteRule 在外键被删除时采用的规则缺省时默认为{@link ForeignKeyRule#RESTRICT}
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder addForeignKey(@NotNull String tableColumn, @Nullable String constraintName,
@NotNull String foreignTable, @NotNull String foreignColumn,
@Nullable ForeignKeyRule updateRule, @Nullable ForeignKeyRule deleteRule);
default String defaultTablesSettings() {
return "ENGINE=InnoDB DEFAULT CHARSET=utf8";
}
}

View File

@ -1,20 +1,20 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.SQLAction;
import java.util.LinkedHashMap;
public interface UpdateBuilder extends ConditionalBuilder<UpdateBuilder, PreparedSQLUpdateAction> {
public interface UpdateBuilder extends ConditionalBuilder<UpdateBuilder, SQLAction<Integer>> {
String getTableName();
String getTableName();
UpdateBuilder setColumnValues(LinkedHashMap<String, Object> columnData);
UpdateBuilder setColumnValues(LinkedHashMap<String, Object> columnData);
UpdateBuilder setColumnValues(String[] columnNames, Object[] columnValues);
UpdateBuilder setColumnValues(String[] columnNames, Object[] columnValues);
default UpdateBuilder setColumnValues(String columnName, Object columnValue) {
return setColumnValues(new String[]{columnName}, new Object[]{columnValue});
}
default UpdateBuilder setColumnValues(String columnName, Object columnValue) {
return setColumnValues(new String[]{columnName}, new Object[]{columnValue});
}
}

View File

@ -1,9 +1,15 @@
package cc.carm.lib.easysql.api.builder;
/**
* 存在则更新不存在则插入
*
* @see ReplaceBuilder
*/
@Deprecated
public interface UpsertBuilder {
String getTableName();
String getTableName();
UpsertBuilder setColumnNames(String[] columnNames, String updateColumn);
UpsertBuilder setColumnNames(String[] columnNames, String updateColumn);
}

View File

@ -0,0 +1,41 @@
package cc.carm.lib.easysql.api.enums;
public enum ForeignKeyRule {
/**
* 啥也不做
* <p>注意 在Mysql中该选项实际上等同于采用默认的 {@link #RESTRICT} 设定
*/
NO_ACTION("NO ACTION"),
/**
* 拒绝删除要求直到使用删除键值的辅助表被手工删除并且没有参照时(这是默认设置也是最安全的设置)
*/
RESTRICT("RESTRICT"),
/**
* 修改包含与已删除键值有参照关系的所有记录使用NULL值替换只能用于已标记为NOT NULL的字段
*/
SET_NULL("SET NULL"),
/**
* 修改包含与已删除键值有参照关系的所有记录使用默认值替换只能用于设定了DEFAULT的字段
*/
SET_DEFAULT("SET DEFAULT"),
/**
* <b>级联删除</b>删除包含与已删除键值有参照关系的所有记录
*/
CASCADE("CASCADE");
String ruleName;
ForeignKeyRule(String ruleName) {
this.ruleName = ruleName;
}
public String getRuleName() {
return ruleName;
}
}

View File

@ -0,0 +1,41 @@
package cc.carm.lib.easysql.api.enums;
public enum IndexType {
/**
* <b>普通索引</b>由关键字KEY或INDEX定义的索引的唯一任务是加快对数据的访问速度
* <br> 因此应该只为那些最经常出现在查询条件WHERE column=或排序条件ORDER BY column中的数据列创建索引
* <br> 只要有可能就应该选择一个数据最整齐最紧凑的数据列如一个整数类型的数据列来创建索引
*/
INDEX("INDEX"),
/**
* <b>唯一索引</b> 是在表上一个或者多个字段组合建立的索引这个或者这些字段的值组合起来在表中不可以重复用于保证数据的唯一性
*/
UNIQUE_KEY("UNIQUE KEY"),
/**
* <b>主键索引</b> 是唯一索引的特定类型表中创建主键时自动创建的索引 一个表只能建立一个主索引
*/
PRIMARY_KEY("PRIMARY KEY"),
/**
* <b>全文索引</b> 主要用来查找文本中的关键字而不是直接与索引中的值相比较
* <br> 请搭配 MATCH 等语句使用而不是使用 WHERE - LIKE
* <br> 全文索引只可用于 CHAR VARCHAR TEXT 系列类型
*/
FULLTEXT_INDEX("FULLTEXT");
String name;
IndexType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,11 @@
package cc.carm.lib.easysql.api.enums;
public enum NumberType {
TINYINT,
SMALLINT,
MEDIUMINT,
INT,
BIGINT
}

View File

@ -7,5 +7,6 @@ import java.util.function.BiConsumer;
@FunctionalInterface
public interface SQLExceptionHandler extends BiConsumer<SQLException, SQLAction<?>> {
}

View File

@ -1,6 +1,7 @@
package cc.carm.lib.easysql.api.function.impl;
package cc.carm.lib.easysql.api.function.defaults;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -37,8 +38,18 @@ public class DefaultSQLExceptionHandler implements SQLExceptionHandler {
@Override
public void accept(SQLException exception, SQLAction<?> sqlAction) {
getLogger().severe("Error when execute [" + sqlAction.getSQLContent() + "]");
getLogger().severe(exception.getLocalizedMessage());
if (sqlAction instanceof SQLUpdateBatchAction) {
getLogger().severe("Error when execute SQLs : ");
int i = 1;
for (String content : ((SQLUpdateBatchAction) sqlAction).getSQLContents()) {
getLogger().severe("#" + i + " {" + content + "}");
i++;
}
} else {
getLogger().severe("Error when execute { " + sqlAction.getSQLContent() + " }");
}
exception.printStackTrace();
}

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-beecp</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>

View File

@ -5,9 +5,18 @@
<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>
<maven.javadoc.skip>true</maven.javadoc.skip>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<artifactId>easysql-demo</artifactId>
<packaging>jar</packaging>
@ -45,15 +54,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>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<dependencies>
<dependency>

View File

@ -1,5 +1,8 @@
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLQuery;
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.api.util.TimeDateUtils;
import cc.carm.lib.easysql.api.util.UUIDUtil;
@ -12,17 +15,39 @@ public class EasySQLDemo {
public void createTable(SQLManager sqlManager) {
// 同步创建表
sqlManager.createTable("users")
.addColumn("id", "INT(11) AUTO_INCREMENT NOT NULL PRIMARY KEY")
// .addColumn("id", "INT(11) AUTO_INCREMENT NOT NULL PRIMARY KEY")
.addAutoIncrementColumn("id", NumberType.INT, true, true)
.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY")
.addColumn("username", "VARCHAR(16) NOT NULL UNIQUE KEY")
.addColumn("age", "INT(3) NOT NULL DEFAULT 1")
.addColumn("username", "VARCHAR(16) NOT NULL")
.addColumn("age", "TINYINT NOT NULL DEFAULT 1")
.addColumn("email", "VARCHAR(32)")
.addColumn("phone", "VARCHAR(16)")
.addColumn("registerTime", "DATETIME NOT NULL")
.addColumn("INDEX `phone`") // 添加索引
// .addColumn("INDEX `phone`") // 原始方法添加索引
.setIndex(IndexType.UNIQUE_KEY, "username") // 添加唯一索引
.setIndex(IndexType.INDEX, "contact", "email", "phone") //添加联合索引 (示例)
.build().execute(null /* 不处理错误 */);
sqlManager.createTable("user_ipaddr")
.addAutoIncrementColumn("id", NumberType.INT, true, true)
.addColumn("uuid", "VARCHAR(32) NOT NULL")
.addColumn("ip", "VARCHAR(16)")
.addColumn("time", "DATETIME NOT NULL")
.addForeignKey("uuid", null,
"users", "uuid",
ForeignKeyRule.CASCADE, ForeignKeyRule.CASCADE
)
.build().execute(null /* 不处理错误 */);
}
public void alertTable(SQLManager sqlManager) {
// 同步更新表
sqlManager.alterTable("users")
.modifyColumn("age", "TINYINT NOT NULL DEFAULT 0")
.execute(null /* 不处理错误 */);
}
public void sqlQuery(SQLManager sqlManager) {
// 同步SQL查询
try (SQLQuery query = sqlManager.createQuery()

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-hikaricp</artifactId>
<name>11-EasySQL-HikariCP</name>
@ -44,14 +51,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>

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>

View File

@ -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 {

View File

@ -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("}");
}
}

View File

@ -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
);
}
}

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
}

91
pom.xml
View File

@ -16,7 +16,7 @@
<groupId>cc.carm.lib</groupId>
<artifactId>easysql-parent</artifactId>
<packaging>pom</packaging>
<version>0.2.10</version>
<version>0.3.0-SNAPSHOT</version>
<modules>
<module>easysql-api</module>
@ -38,6 +38,7 @@
<name>Carm Jos</name>
<email>carm@carm.cc</email>
<url>https://www.carm.cc</url>
<timezone>Asia/Shanghai</timezone>
</developer>
</developers>
@ -45,6 +46,7 @@
<connection>scm:git:git@github.com:CarmJos/EasySQL.git</connection>
<developerConnection>scm:git:git@github.com:CarmJos/EasySQL.git</developerConnection>
<url>https://github.com/CarmJos/EasySQL</url>
<tag>HEAD</tag>
</scm>
<licenses>
@ -93,12 +95,11 @@
<distributionManagement>
<downloadUrl>${project.url}/releases</downloadUrl>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/CarmJos/EasySQL</url>
</repository>
<site>
<id>easysql-javadoc</id>
<name>EasySQL JavaDoc (on Github Pages)</name>
<url>https://carmjos.github.io/EasySQL</url>
</site>
</distributionManagement>
@ -128,20 +129,39 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<!-- <plugin>-->
<!-- <groupId>org.apache.maven.plugins</groupId>-->
<!-- <artifactId>maven-gpg-plugin</artifactId>-->
<!-- <version>1.5</version>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <id>sign-artifacts</id>-->
<!-- <phase>verify</phase>-->
<!-- <goals>-->
<!-- <goal>sign</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
<configuration>
<keyname>0x37986DF7</keyname>
<passphraseServerId>0x37986DF7</passphraseServerId>
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<useReleaseProfile>false</useReleaseProfile>
<releaseProfiles>release</releaseProfiles>
<goals>deploy</goals>
</configuration>
</plugin>
</plugins>
<pluginManagement>
@ -253,5 +273,34 @@
</build>
<profiles>
<profile>
<id>ossrh</id>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
<profile>
<id>github</id>
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/CarmJos/EasySQL</url>
</repository>
</distributionManagement>
</profile>
</profiles>
</project>