This commit is contained in:
Looly
2022-09-30 23:00:15 +08:00
parent 00fad42926
commit d6be80f8ea
22 changed files with 173 additions and 130 deletions

View File

@@ -17,7 +17,7 @@ import cn.hutool.db.sql.Query;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.db.sql.SqlExecutor;
import cn.hutool.db.sql.SqlUtil;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.db.sql.QuoteWrapper;
import javax.sql.DataSource;
import java.io.Serializable;
@@ -33,6 +33,7 @@ import java.util.Map;
* 通过给定的数据源执行给定SQL或者给定数据源和方言执行相应的CRUD操作<br>
* 提供抽象方法getConnection和closeConnection用于自定义数据库连接的打开和关闭
*
* @param <R> return this类型
* @author looly
*/
public abstract class AbstractDb<R extends AbstractDb<R>> extends DefaultConnectionHolder implements Serializable {
@@ -925,19 +926,19 @@ public abstract class AbstractDb<R extends AbstractDb<R>> extends DefaultConnect
* @since 4.0.0
*/
public R setWrapper(final Character wrapperChar) {
return setWrapper(new Wrapper(wrapperChar));
return setWrapper(new QuoteWrapper(wrapperChar));
}
/**
* 设置包装器,包装器用于对表名、字段名进行符号包装(例如双引号),防止关键字与这些表名或字段冲突
*
* @param wrapper 包装器null表示取消包装
* @param quoteWrapper 包装器null表示取消包装
* @return this
* @since 4.0.0
*/
@SuppressWarnings("unchecked")
public R setWrapper(final Wrapper wrapper) {
this.runner.setWrapper(wrapper);
public R setWrapper(final QuoteWrapper quoteWrapper) {
this.runner.setWrapper(quoteWrapper);
return (R) this;
}
@@ -949,7 +950,7 @@ public abstract class AbstractDb<R extends AbstractDb<R>> extends DefaultConnect
* @since 4.5.7
*/
public R disableWrapper() {
return setWrapper((Wrapper) null);
return setWrapper((QuoteWrapper) null);
}
// ---------------------------------------------------------------------------- Getters and Setters end

View File

@@ -13,7 +13,7 @@ import cn.hutool.db.sql.Query;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.db.sql.SqlExecutor;
import cn.hutool.db.sql.SqlUtil;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.db.sql.QuoteWrapper;
import java.io.Serializable;
import java.sql.Connection;
@@ -428,16 +428,16 @@ public class DialectRunner implements Serializable {
* @param wrapperChar 包装字符字符会在SQL生成时位于表名和字段名两边null时表示取消包装
*/
public void setWrapper(final Character wrapperChar) {
setWrapper(new Wrapper(wrapperChar));
setWrapper(new QuoteWrapper(wrapperChar));
}
/**
* 设置包装器,包装器用于对表名、字段名进行符号包装(例如双引号),防止关键字与这些表名或字段冲突
*
* @param wrapper 包装器null表示取消包装
* @param quoteWrapper 包装器null表示取消包装
*/
public void setWrapper(final Wrapper wrapper) {
this.dialect.setWrapper(wrapper);
public void setWrapper(final QuoteWrapper quoteWrapper) {
this.dialect.setWrapper(quoteWrapper);
}
//---------------------------------------------------------------------------- Getters and Setters end

View File

@@ -5,7 +5,7 @@ import cn.hutool.db.Page;
import cn.hutool.db.sql.Order;
import cn.hutool.db.sql.Query;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.db.sql.QuoteWrapper;
import java.io.Serializable;
import java.sql.Connection;
@@ -24,14 +24,14 @@ public interface Dialect extends Serializable {
/**
* @return 包装器
*/
Wrapper getWrapper();
QuoteWrapper getWrapper();
/**
* 设置包装器
*
* @param wrapper 包装器
* @param quoteWrapper 包装器
*/
void setWrapper(Wrapper wrapper);
void setWrapper(QuoteWrapper quoteWrapper);
// -------------------------------------------- Execute

View File

@@ -13,7 +13,7 @@ import cn.hutool.db.dialect.DialectName;
import cn.hutool.db.sql.Condition;
import cn.hutool.db.sql.Query;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.db.sql.QuoteWrapper;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -29,21 +29,21 @@ import java.util.Set;
public class AnsiSqlDialect implements Dialect {
private static final long serialVersionUID = 2088101129774974580L;
protected Wrapper wrapper = new Wrapper();
protected QuoteWrapper quoteWrapper = new QuoteWrapper();
@Override
public Wrapper getWrapper() {
return this.wrapper;
public QuoteWrapper getWrapper() {
return this.quoteWrapper;
}
@Override
public void setWrapper(final Wrapper wrapper) {
this.wrapper = wrapper;
public void setWrapper(final QuoteWrapper quoteWrapper) {
this.quoteWrapper = quoteWrapper;
}
@Override
public PreparedStatement psForInsert(final Connection conn, final Entity entity) throws SQLException {
final SqlBuilder insert = SqlBuilder.of(wrapper).insert(entity, this.dialectName());
final SqlBuilder insert = SqlBuilder.of(quoteWrapper).insert(entity, this.dialectName());
return StatementUtil.prepareStatement(conn, insert);
}
@@ -54,7 +54,7 @@ public class AnsiSqlDialect implements Dialect {
throw new DbRuntimeException("Entities for batch insert is empty !");
}
// 批量根据第一行数据结构生成SQL占位符
final SqlBuilder insert = SqlBuilder.of(wrapper).insert(entities[0], this.dialectName());
final SqlBuilder insert = SqlBuilder.of(quoteWrapper).insert(entities[0], this.dialectName());
final Set<String> fields = CollUtil.filter(entities[0].keySet(), StrUtil::isNotBlank);
return StatementUtil.prepareStatementForBatch(conn, insert.build(), fields, entities);
}
@@ -68,7 +68,7 @@ public class AnsiSqlDialect implements Dialect {
// 对于无条件删除语句直接抛出异常禁止,防止误删除
throw new SQLException("No 'WHERE' condition, we can't prepared statement for delete everything.");
}
final SqlBuilder delete = SqlBuilder.of(wrapper).delete(query.getFirstTableName()).where(where);
final SqlBuilder delete = SqlBuilder.of(quoteWrapper).delete(query.getFirstTableName()).where(where);
return StatementUtil.prepareStatement(conn, delete);
}
@@ -83,7 +83,7 @@ public class AnsiSqlDialect implements Dialect {
throw new SQLException("No 'WHERE' condition, we can't prepare statement for update everything.");
}
final SqlBuilder update = SqlBuilder.of(wrapper).update(entity).where(where);
final SqlBuilder update = SqlBuilder.of(quoteWrapper).update(entity).where(where);
return StatementUtil.prepareStatement(conn, update);
}
@@ -100,7 +100,7 @@ public class AnsiSqlDialect implements Dialect {
throw new DbRuntimeException("Table name must be not empty !");
}
final SqlBuilder find = SqlBuilder.of(wrapper).query(query);
final SqlBuilder find = SqlBuilder.of(quoteWrapper).query(query);
return psForPage(conn, find, query.getPage());
}

View File

@@ -40,7 +40,7 @@ public class H2Dialect extends AnsiSqlDialect {
public PreparedStatement psForUpsert(final Connection conn, final Entity entity, final String... keys) throws SQLException {
Assert.notEmpty(keys, "Keys must be not empty for H2 MERGE SQL.");
SqlBuilder.validateEntity(entity);
final SqlBuilder builder = SqlBuilder.of(wrapper);
final SqlBuilder builder = SqlBuilder.of(quoteWrapper);
final StringBuilder fieldsPart = new StringBuilder();
final StringBuilder placeHolder = new StringBuilder();
@@ -54,15 +54,15 @@ public class H2Dialect extends AnsiSqlDialect {
placeHolder.append(", ");
}
fieldsPart.append((null != wrapper) ? wrapper.wrap(field) : field);
fieldsPart.append((null != quoteWrapper) ? quoteWrapper.wrap(field) : field);
placeHolder.append("?");
builder.addParams(value);
}
});
String tableName = entity.getTableName();
if (null != this.wrapper) {
tableName = this.wrapper.wrap(tableName);
if (null != this.quoteWrapper) {
tableName = this.quoteWrapper.wrap(tableName);
}
builder.append("MERGE INTO ").append(tableName)
// 字段列表

View File

@@ -6,7 +6,7 @@ import cn.hutool.db.Page;
import cn.hutool.db.StatementUtil;
import cn.hutool.db.dialect.DialectName;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.db.sql.QuoteWrapper;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -21,7 +21,7 @@ public class MysqlDialect extends AnsiSqlDialect{
private static final long serialVersionUID = -3734718212043823636L;
public MysqlDialect() {
wrapper = new Wrapper('`');
quoteWrapper = new QuoteWrapper('`');
}
@Override
@@ -51,7 +51,7 @@ public class MysqlDialect extends AnsiSqlDialect{
@Override
public PreparedStatement psForUpsert(final Connection conn, final Entity entity, final String... keys) throws SQLException {
SqlBuilder.validateEntity(entity);
final SqlBuilder builder = SqlBuilder.of(wrapper);
final SqlBuilder builder = SqlBuilder.of(quoteWrapper);
final StringBuilder fieldsPart = new StringBuilder();
final StringBuilder placeHolder = new StringBuilder();
@@ -67,7 +67,7 @@ public class MysqlDialect extends AnsiSqlDialect{
updateHolder.append(", ");
}
field = (null != wrapper) ? wrapper.wrap(field) : field;
field = (null != quoteWrapper) ? quoteWrapper.wrap(field) : field;
fieldsPart.append(field);
updateHolder.append(field).append("=values(").append(field).append(")");
placeHolder.append("?");
@@ -76,8 +76,8 @@ public class MysqlDialect extends AnsiSqlDialect{
});
String tableName = entity.getTableName();
if (null != this.wrapper) {
tableName = this.wrapper.wrap(tableName);
if (null != this.quoteWrapper) {
tableName = this.quoteWrapper.wrap(tableName);
}
builder.append("INSERT INTO ").append(tableName)
// 字段列表

View File

@@ -7,7 +7,7 @@ import cn.hutool.db.Entity;
import cn.hutool.db.StatementUtil;
import cn.hutool.db.dialect.DialectName;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.db.sql.QuoteWrapper;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -23,7 +23,7 @@ public class PostgresqlDialect extends AnsiSqlDialect{
private static final long serialVersionUID = 3889210427543389642L;
public PostgresqlDialect() {
wrapper = new Wrapper('"');
quoteWrapper = new QuoteWrapper('"');
}
@Override
@@ -35,7 +35,7 @@ public class PostgresqlDialect extends AnsiSqlDialect{
public PreparedStatement psForUpsert(final Connection conn, final Entity entity, final String... keys) throws SQLException {
Assert.notEmpty(keys, "Keys must be not empty for Postgres.");
SqlBuilder.validateEntity(entity);
final SqlBuilder builder = SqlBuilder.of(wrapper);
final SqlBuilder builder = SqlBuilder.of(quoteWrapper);
final StringBuilder fieldsPart = new StringBuilder();
final StringBuilder placeHolder = new StringBuilder();
@@ -51,7 +51,7 @@ public class PostgresqlDialect extends AnsiSqlDialect{
updateHolder.append(", ");
}
final String wrapedField = (null != wrapper) ? wrapper.wrap(field) : field;
final String wrapedField = (null != quoteWrapper) ? quoteWrapper.wrap(field) : field;
fieldsPart.append(wrapedField);
updateHolder.append(wrapedField).append("=EXCLUDED.").append(field);
placeHolder.append("?");
@@ -60,8 +60,8 @@ public class PostgresqlDialect extends AnsiSqlDialect{
});
String tableName = entity.getTableName();
if (null != this.wrapper) {
tableName = this.wrapper.wrap(tableName);
if (null != this.quoteWrapper) {
tableName = this.quoteWrapper.wrap(tableName);
}
builder.append("INSERT INTO ").append(tableName)
// 字段列表

View File

@@ -4,7 +4,7 @@ import cn.hutool.core.text.StrUtil;
import cn.hutool.db.Page;
import cn.hutool.db.dialect.DialectName;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.db.sql.QuoteWrapper;
/**
* SQLServer2012 方言
@@ -17,7 +17,7 @@ public class SqlServer2012Dialect extends AnsiSqlDialect {
public SqlServer2012Dialect() {
//双引号和中括号适用,双引号更广泛
wrapper = new Wrapper('"');
quoteWrapper = new QuoteWrapper('"');
}
@Override

View File

@@ -1,7 +1,7 @@
package cn.hutool.db.dialect.impl;
import cn.hutool.db.dialect.DialectName;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.db.sql.QuoteWrapper;
/**
* SqlLite3方言
@@ -12,9 +12,9 @@ public class Sqlite3Dialect extends AnsiSqlDialect{
private static final long serialVersionUID = -3527642408849291634L;
public Sqlite3Dialect() {
wrapper = new Wrapper('[', ']');
quoteWrapper = new QuoteWrapper('[', ']');
}
@Override
public String dialectName() {
return DialectName.SQLITE3.name();

View File

@@ -2,6 +2,7 @@ package cn.hutool.db.ds;
import cn.hutool.core.exceptions.CloneRuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.func.Wrapper;
import javax.sql.DataSource;
import java.io.Closeable;
@@ -21,7 +22,7 @@ import java.util.logging.Logger;
* @author looly
* @since 4.3.2
*/
public class DataSourceWrapper implements DataSource, Closeable, Cloneable {
public class DataSourceWrapper implements Wrapper<DataSource>, DataSource, Closeable, Cloneable {
private final DataSource ds;
private final String driver;
@@ -62,6 +63,7 @@ public class DataSourceWrapper implements DataSource, Closeable, Cloneable {
*
* @return 原始数据源
*/
@Override
public DataSource getRaw() {
return this.ds;
}

View File

@@ -12,12 +12,12 @@ import java.util.Collection;
import java.util.Map.Entry;
/**
* 包装器<br>
* 字段和表明包装器<br>
* 主要用于字段名的包装在字段名的前后加字符例如反引号来避免与数据库的关键字冲突
*
* @author Looly
*/
public class Wrapper implements Serializable {
public class QuoteWrapper implements Serializable {
private static final long serialVersionUID = 1L;
/**
@@ -29,7 +29,10 @@ public class Wrapper implements Serializable {
*/
private Character sufWrapQuote;
public Wrapper() {
/**
* 构造
*/
public QuoteWrapper() {
}
/**
@@ -37,7 +40,7 @@ public class Wrapper implements Serializable {
*
* @param wrapQuote 单包装字符
*/
public Wrapper(final Character wrapQuote) {
public QuoteWrapper(final Character wrapQuote) {
this.preWrapQuote = wrapQuote;
this.sufWrapQuote = wrapQuote;
}
@@ -48,7 +51,7 @@ public class Wrapper implements Serializable {
* @param preWrapQuote 前置包装符号
* @param sufWrapQuote 后置包装符号
*/
public Wrapper(final Character preWrapQuote, final Character sufWrapQuote) {
public QuoteWrapper(final Character preWrapQuote, final Character sufWrapQuote) {
this.preWrapQuote = preWrapQuote;
this.sufWrapQuote = sufWrapQuote;
}

View File

@@ -39,11 +39,11 @@ public class SqlBuilder implements Builder<String> {
/**
* 创建SQL构建器
*
* @param wrapper 包装器
* @param quoteWrapper 包装器
* @return SQL构建器
*/
public static SqlBuilder of(final Wrapper wrapper) {
return new SqlBuilder(wrapper);
public static SqlBuilder of(final QuoteWrapper quoteWrapper) {
return new SqlBuilder(quoteWrapper);
}
/**
@@ -112,14 +112,14 @@ public class SqlBuilder implements Builder<String> {
/**
* 包装器
*/
private Wrapper wrapper;
private QuoteWrapper quoteWrapper;
// --------------------------------------------------------------- Constructor start
public SqlBuilder() {
}
public SqlBuilder(final Wrapper wrapper) {
this.wrapper = wrapper;
public SqlBuilder(final QuoteWrapper quoteWrapper) {
this.quoteWrapper = quoteWrapper;
}
// --------------------------------------------------------------- Constructor end
@@ -172,7 +172,7 @@ public class SqlBuilder implements Builder<String> {
placeHolder.append(", ");
}
fieldsPart.append((null != wrapper) ? wrapper.wrap(field) : field);
fieldsPart.append((null != quoteWrapper) ? quoteWrapper.wrap(field) : field);
if (isOracle && OracleDialect.isNextVal(value)) {
// Oracle的特殊自增键通过字段名.nextval获得下一个值
placeHolder.append(value);
@@ -192,9 +192,9 @@ public class SqlBuilder implements Builder<String> {
}
String tableName = entity.getTableName();
if (null != this.wrapper) {
if (null != this.quoteWrapper) {
// 包装表名 entity = wrapper.wrap(entity);
tableName = this.wrapper.wrap(tableName);
tableName = this.quoteWrapper.wrap(tableName);
}
sql.append(tableName)
.append(" (").append(fieldsPart).append(") VALUES (")//
@@ -214,9 +214,9 @@ public class SqlBuilder implements Builder<String> {
throw new DbRuntimeException("Table name is blank !");
}
if (null != wrapper) {
if (null != quoteWrapper) {
// 包装表名
tableName = wrapper.wrap(tableName);
tableName = quoteWrapper.wrap(tableName);
}
sql.append("DELETE FROM ").append(tableName);
@@ -235,9 +235,9 @@ public class SqlBuilder implements Builder<String> {
validateEntity(entity);
String tableName = entity.getTableName();
if (null != wrapper) {
if (null != quoteWrapper) {
// 包装表名
tableName = wrapper.wrap(tableName);
tableName = quoteWrapper.wrap(tableName);
}
sql.append("UPDATE ").append(tableName).append(" SET ");
@@ -246,7 +246,7 @@ public class SqlBuilder implements Builder<String> {
if (paramValues.size() > 0) {
sql.append(", ");
}
sql.append((null != wrapper) ? wrapper.wrap(field) : field).append(" = ? ");
sql.append((null != quoteWrapper) ? quoteWrapper.wrap(field) : field).append(" = ? ");
this.paramValues.add(value);// 更新不对空做处理,因为存在清空字段的情况
}
});
@@ -280,9 +280,9 @@ public class SqlBuilder implements Builder<String> {
if (CollUtil.isEmpty(fields)) {
sql.append("*");
} else {
if (null != wrapper) {
if (null != quoteWrapper) {
// 包装字段名
fields = wrapper.wrap(fields);
fields = quoteWrapper.wrap(fields);
}
sql.append(CollUtil.join(fields, StrUtil.COMMA));
}
@@ -321,9 +321,9 @@ public class SqlBuilder implements Builder<String> {
throw new DbRuntimeException("Table name is blank in table names !");
}
if (null != wrapper) {
if (null != quoteWrapper) {
// 包装表名
tableNames = wrapper.wrap(tableNames);
tableNames = quoteWrapper.wrap(tableNames);
}
sql.append(" FROM ").append(ArrayUtil.join(tableNames, StrUtil.COMMA));
@@ -369,7 +369,7 @@ public class SqlBuilder implements Builder<String> {
*/
@SuppressWarnings("unchecked")
public <T> SqlBuilder in(final String field, final T... values) {
sql.append(wrapper.wrap(field)).append(" IN ").append("(").append(ArrayUtil.join(values, StrUtil.COMMA)).append(")");
sql.append(quoteWrapper.wrap(field)).append(" IN ").append("(").append(ArrayUtil.join(values, StrUtil.COMMA)).append(")");
return this;
}
@@ -381,9 +381,9 @@ public class SqlBuilder implements Builder<String> {
*/
public SqlBuilder groupBy(String... fields) {
if (ArrayUtil.isNotEmpty(fields)) {
if (null != wrapper) {
if (null != quoteWrapper) {
// 包装字段名
fields = wrapper.wrap(fields);
fields = quoteWrapper.wrap(fields);
}
sql.append(" GROUP BY ").append(ArrayUtil.join(fields, StrUtil.COMMA));
@@ -436,9 +436,9 @@ public class SqlBuilder implements Builder<String> {
boolean isFirst = true;
for (final Order order : orders) {
field = order.getField();
if (null != wrapper) {
if (null != quoteWrapper) {
// 包装字段名
field = wrapper.wrap(field);
field = quoteWrapper.wrap(field);
}
if (StrUtil.isBlank(field)) {
continue;
@@ -473,9 +473,9 @@ public class SqlBuilder implements Builder<String> {
if (null != join) {
sql.append(StrUtil.SPACE).append(join).append(" JOIN ");
if (null != wrapper) {
if (null != quoteWrapper) {
// 包装表名
tableName = wrapper.wrap(tableName);
tableName = quoteWrapper.wrap(tableName);
}
sql.append(tableName);
}
@@ -623,9 +623,9 @@ public class SqlBuilder implements Builder<String> {
return StrUtil.EMPTY;
}
if (null != wrapper) {
if (null != quoteWrapper) {
// 包装字段名
conditions = wrapper.wrap(conditions);
conditions = quoteWrapper.wrap(conditions);
}
return ConditionBuilder.of(conditions).build(this.paramValues);

View File

@@ -1,5 +1,7 @@
package cn.hutool.db.sql;
import cn.hutool.core.lang.func.Wrapper;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
@@ -35,7 +37,7 @@ import java.util.Calendar;
* @author looly
* @since 4.1.0
*/
public class StatementWrapper implements PreparedStatement {
public class StatementWrapper implements PreparedStatement, Wrapper<PreparedStatement> {
private final PreparedStatement rawStatement;
@@ -544,4 +546,8 @@ public class StatementWrapper implements PreparedStatement {
rawStatement.setNClob(parameterIndex, reader);
}
@Override
public PreparedStatement getRaw() {
return rawStatement;
}
}