ifHasValue() {
+ return new DbUpdateForStartByField<>(this, SkipType.BLANK_VALUE);
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhere.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhere.java
index 59de92b9987a371d606df8f1f1213642b9242da2..d407bfca87588e3444e5597a715afc1a2422c5be 100644
--- a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhere.java
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhere.java
@@ -1,16 +1,10 @@
package com.gitee.qdbp.able.jdbc.condition;
-import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import com.gitee.qdbp.able.beans.Copyable;
import com.gitee.qdbp.able.enums.LogicType;
-import com.gitee.qdbp.able.enums.MatchType;
import com.gitee.qdbp.able.jdbc.base.DbCondition;
-import com.gitee.qdbp.able.jdbc.base.LogicCondition;
-import com.gitee.qdbp.able.jdbc.base.MatchCondition;
-import com.gitee.qdbp.able.jdbc.base.WhereCondition;
-import com.gitee.qdbp.able.jdbc.model.LikeValue;
import com.gitee.qdbp.tools.utils.VerifyTools;
/**
@@ -18,50 +12,50 @@ import com.gitee.qdbp.tools.utils.VerifyTools;
*
DbWhere where = new DbWhere();
// [SQL] AND ID = :$1
- where.andEquals("id", entity.getId());
+ where.on("id").equals(entity.getId());
// [SQL] AND ID != :$1
- where.andNotEquals("id", entity.getId());
+ where.on("id").notEquals(entity.getId());
// [SQL] AND CREATE_TIME > :$1
- where.andGreaterThen("createTime", new Date());
+ where.on("createTime").greaterThen(new Date());
// [SQL] AND CREATE_TIME >= :$1
- where.andGreaterEqualsThen("createTime", new Date());
+ where.on("createTime").greaterEqualsThen(new Date());
// [SQL] AND CREATE_TIME < :$1
- where.andLessThen("createTime", new Date());
+ where.on("createTime").lessThen(new Date());
// [SQL] AND CREATE_TIME <= :$1
- where.andLessEqualsThen("createTime", new Date());
+ where.on("createTime").lessEqualsThen(new Date());
// [SQL] AND USER_STATE IS NULL
- where.andIsNull("userState");
+ where.on("userState").isNull();
// [SQL] AND USER_STATE IS NOT NULL
- where.andIsNotNull("userState");
+ where.on("userState").isNotNull();
// [ORACLE/DB2] AND USER_NAME LIKE('%'||:$1||'%')
// [MYSQL] AND USER_NAME LIKE CONCAT('%',:$1,'%')
- where.andLike("userName", entity.getUserName());
+ where.on("userName").like(entity.getUserName());
// [ORACLE/DB2] AND USER_NAME NOT LIKE('%'||:$1||'%')
// [MYSQL] AND USER_NAME NOT LIKE CONCAT('%',:$1,'%')
- where.andNotLike("userName", entity.getUserName());
+ where.on("userName").notLkie(entity.getUserName());
// [ORACLE/DB2] AND PHONE LIKE(:$1||'%')
// [MYSQL] AND PHONE LIKE CONCAT(:$1,'%')
- where.andStarts("phone", "139");
+ where.on("phone").startsWith("139");
// [ORACLE/DB2] AND PHONE LIKE('%'||:$1)
// [MYSQL] AND PHONE LIKE CONCAT('%',:$1)
- where.andEnds("phone", "8888");
+ where.on("phone").endsWith("8888");
// [SQL] AND USER_STATE IN (:$1, :$2, ...)
- where.andIn("userState", UserState.NORMAL, UserState.LOCKED, ...);
+ where.on("userState").in(UserState.NORMAL, UserState.LOCKED, ...);
// [SQL] AND USER_STATE NOT IN (:$1, :$2, ...)
- where.andNotIn("userState", UserState.NORMAL, UserState.LOCKED, ...);
+ where.on("userState").notIn(UserState.NORMAL, UserState.LOCKED, ...);
// [SQL] AND CREATE_TIME BETWEEN :$1 AND :$2
- where.andBetween("createTime", entity.getStartTime(), entity.getEndTime());
+ where.on("createTime").between(entity.getStartTime(), entity.getEndTime());
// [SQL] AND ( USER_NAME LIKE '%'||:$1||'%' OR REAL_NAME LIKE '%'||:$2||'%' )
- where.andSubCondition(new SubCondition() { // 子条件
+ where.on().subCondition(new SubCondition() { // 子条件
public void build(DbWhere w) {
- w.orLike("userName", entity.getKeyword())
- .orLike("realName", entity.getKeyword());
+ w.on("userName").like(entity.getKeyword())
+ .or("realName").like(entity.getKeyword());
}
});
// JDK8
- where.andSubCondition((w) -> { // 子条件
- w.orLike("userName", entity.getKeyword())
- .orLike("realName", entity.getKeyword());
+ where.on().subCondition((w) -> { // 子条件
+ w.on("userName").like(entity.getKeyword())
+ .or("realName").like(entity.getKeyword());
});
*
*
@@ -76,1664 +70,84 @@ public class DbWhere extends DbItems implements Copyable {
/** 没有查询条件的空Where **/
public static final DbWhere NONE = new ReadonlyWhere();
- /**
- * Where条件
- * 字段名可以带表别名, 如where.on("u.id", "=", entity.getId());
- *
- * @param fieldName 字段名称
- * @param operate 目前支持如下操作:
- * =, !=, <, <=, >, >=,
- * Equals(equals), NotEquals(not equals),
- * LessThen(less then), LessEqualsThen(less equals then),
- * GreaterThen(greater then), GreaterEqualsThen(greater equals then),
- * IsNull(is null), IsNotNull(is not null),
- * Like(like), NotLike(not like),
- * Starts(starts), NotStarts(not starts), Ends(ends), NotEnds(not ends),
- * In(in), NotIn(not in), Between(between), NotBetween(not between)
- * @param fieldValues 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere on(String fieldName, String operate, Object... fieldValues) {
- return this.and(fieldName, operate, fieldValues);
- }
-
- /** 增加自定义条件 **/
- public DbWhere on(WhereCondition condition) {
- super.put(condition);
- return this;
- }
-
- /**
- * AND查询条件
- *
- * @param fieldName 字段名称
- * @param operate 操作符
- * @param fieldValues 字段值
- * @return 返回容器自身, 用于链式操作
- */
- protected DbWhere and(String fieldName, String operate, Object... fieldValues) {
- DbField condition = parseField(LogicType.AND, fieldName, operate, fieldValues);
- this.put(condition);
- return this;
- }
-
- /**
- * OR查询条件
- *
- * @param fieldName 字段名称
- * @param operate 操作符
- * @param fieldValues 字段值
- * @return 返回容器自身, 用于链式操作
- */
- protected DbWhere or(String fieldName, String operate, Object... fieldValues) {
- DbField condition = parseField(LogicType.OR, fieldName, operate, fieldValues);
- this.put(condition);
- return this;
- }
-
- /**
- * AND查询条件
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名称
- * @param operate 操作符
- * @param fieldValues 字段值
- * @return 返回容器自身, 用于链式操作
- */
- protected DbWhere andIf(boolean asserts, String fieldName, String operate, Object... fieldValues) {
- if (asserts) {
- DbField condition = parseField(LogicType.AND, fieldName, operate, fieldValues);
- this.put(condition);
- }
- return this;
- }
-
- /**
- * OR查询条件
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名称
- * @param operate 操作符
- * @param fieldValues 字段值
- * @return 返回容器自身, 用于链式操作
- */
- protected DbWhere orIf(boolean asserts, String fieldName, String operate, Object... fieldValues) {
- if (asserts) {
- DbField condition = parseField(LogicType.OR, fieldName, operate, fieldValues);
- this.put(condition);
- }
- return this;
- }
-
- /**
- * 增加条件
- *
- * @param condition 条件
- */
- @Override
- protected void put(DbField condition) {
- VerifyTools.requireNonNull(condition, "condition");
- if (condition instanceof Field) {
- super.put(condition);
- } else {
- super.put(new Field(LogicType.AND, condition));
- }
- }
-
- /**
- * 增加条件
- *
- * @param condition 自定义条件
- */
- @Override
- protected void put(DbCondition condition) {
- VerifyTools.requireNonNull(condition, "condition");
- if (condition instanceof Field) {
- super.put(condition);
- } else if (condition instanceof DbField) {
- super.put(new Field(LogicType.AND, (DbField) condition));
- } else {
- super.put(condition);
- }
- }
-
- protected Field parseField(LogicType logicType, String fieldName, String operate, Object... fieldValues) {
- VerifyTools.nvl(fieldName, "fieldName");
- Field condition = new Field(logicType);
- condition.setFieldName(fieldName);
- condition.setOperateType(operate);
- if (fieldValues != null && fieldValues.length > 0) {
- if (fieldValues.length == 1) {
- condition.setFieldValue(fieldValues[0]);
- } else {
- condition.setFieldValue(fieldValues);
- }
- }
- return condition;
- }
-
- /**
- * 创建子查询条件
- *
- * @param logicType 逻辑类型 AND/OR 这里指的是容器内部子条件项之间默认的连接类型
- * @return 子查询条件容器
- * @deprecated 这里的逻辑类型并不是此容器的连接类型
- * 而是容器内部子条件项之间使用on()方法时使用的连接类型, 不符合一般理解
- * 改为{@link #andSubCondition(SubCondition)}
- * {@link #andNotSubCondition(SubCondition)}
- * {@link #orSubCondition(SubCondition)}
- * {@link #orNotSubCondition(SubCondition)}
- */
- @Deprecated
- public SubWhere sub(String logicType) {
- return this.sub(logicType, true);
- }
-
- /**
- * 创建子查询条件容器
- *
- * @param logicType 逻辑类型 AND/OR 这里指的是容器内部子条件项之间默认的连接类型
- * @param positive 匹配模式 肯定模式还是否定模式
- * @return 子查询条件容器
- * @deprecated 这里的逻辑类型并不是此容器的连接类型
- * 而是容器内部子条件项之间使用on()方法时使用的连接类型, 不符合一般理解
- * 改为{@link #andSubCondition(SubCondition)}
- * {@link #andNotSubCondition(SubCondition)}
- * {@link #orSubCondition(SubCondition)}
- * {@link #orNotSubCondition(SubCondition)}
- */
- @Deprecated
- public SubWhere sub(String logicType, boolean positive) {
- VerifyTools.nvl(logicType, "logicType");
- LogicType innerLogicType;
- if ("AND".equalsIgnoreCase(logicType)) {
- innerLogicType = LogicType.AND;
- } else if ("OR".equalsIgnoreCase(logicType)) {
- innerLogicType = LogicType.OR;
- } else {
- String msg = "Unsupported logic type: " + logicType + ". acceptable values are: 'AND', 'OR'.";
- throw new IllegalArgumentException(msg);
- }
- MatchType matchType = positive ? MatchType.Positive : MatchType.Negative;
- SubWhere sub = new InnerSubWhere(this, LogicType.AND, matchType, innerLogicType);
- this.put(sub);
- return sub;
- }
-
- /**
- * 克隆为新对象(如果子类有新增字段或没有默认构造函数就应该覆盖该方法)
- *
- * @return 新对象
- * @since 5.0.0
- */
- @Override
- public DbWhere copy() {
- DbWhere copies = newCopies();
- this.copyTo(copies);
- return copies;
- }
-
- protected void copyTo(DbWhere copies) {
- Iterator iterator = this.iterator();
- while (iterator.hasNext()) {
- DbCondition item = iterator.next();
- if (item instanceof Field) {
- copies.put(((Field) item).copy());
- } else if (item instanceof DbField) {
- copies.put(((DbField) item).copy());
- } else if (item instanceof SubWhere) {
- copies.put(((SubWhere) item).copy().setParent(copies));
- } else if (item instanceof DbWhere) {
- copies.put(((DbWhere) item).copy());
- } else if (item instanceof Copyable) {
- DbCondition newer = (DbCondition) ((Copyable) item).copy();
- copies.put(newer);
- } else { // DbCondition/DbConditions
- copies.put(item); // 无法克隆为副本
- }
- }
- }
-
- /**
- * 创建副本对象(如果子类没有默认构造函数就应该覆盖该方法)
- *
- * @return 副本对象
- * @since 5.0.0
- */
- protected DbWhere newCopies() {
- if (this.getClass() == DbWhere.class) { // 当前类
- return new DbWhere();
- } else { // 子类
- try {
- return this.getClass().newInstance();
- } catch (Exception e) {
- throw new IllegalStateException("CloneNotSupported, FailedToInvokeDefaultConstructor.");
- }
- }
- }
-
- /**
- * 根据字段名称替换条件
- *
- * @param fieldName 字段名称
- * @return 替换了几个条件
- */
- public int replace(String fieldName, String operate, Object... fieldValues) {
- DbField condition = parseField(null, fieldName, operate, fieldValues);
- int count = this.replace(condition);
- if (count == 0) {
- this.put(condition);
- count++;
- }
- return count;
- }
-
- /**
- * 等于条件
- * [SQL] AND fieldName = fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andEquals(String fieldName, Object fieldValue) {
- return this.and(fieldName, "=", fieldValue);
- }
-
- /**
- * 不等于条件
- * [SQL] AND fieldName != fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotEquals(String fieldName, Object fieldValue) {
- return this.and(fieldName, "!=", fieldValue);
- }
-
- /**
- * 小于条件
- * [SQL] AND fieldName < fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andLessThen(String fieldName, Object fieldValue) {
- return this.and(fieldName, "<", fieldValue);
- }
-
- /**
- * 小于等于条件
- * [SQL] AND fieldName <= fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andLessEqualsThen(String fieldName, Object fieldValue) {
- return this.and(fieldName, "<=", fieldValue);
- }
-
- /**
- * 大于条件
- * [SQL] AND fieldName > fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andGreaterThen(String fieldName, Object fieldValue) {
- return this.and(fieldName, ">", fieldValue);
- }
-
- /**
- * 大于等于条件
- * [SQL] AND fieldName >= fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andGreaterEqualsThen(String fieldName, Object fieldValue) {
- return this.and(fieldName, ">=", fieldValue);
- }
-
- /**
- * IS NULL条件
- * [SQL] AND fieldName IS NULL
- *
- * @param fieldName 字段名
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andIsNull(String fieldName) {
- return this.and(fieldName, "is null");
- }
-
- /**
- * IS NOT NULL条件
- * [SQL] AND fieldName IS NOT NULL
- *
- * @param fieldName 字段名
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andIsNotNull(String fieldName) {
- return this.and(fieldName, "is not null");
- }
-
- /**
- * LIKE条件
- * [ORACLE/DB2] AND fieldName LIKE('%'||fieldValue||'%')
- * [MYSQL] AND fieldName LIKE CONCAT('%',fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找带有%的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andLike(String, LikeValue)
- */
- public DbWhere andLike(String fieldName, String fieldValue) {
- return this.and(fieldName, "like", fieldValue);
- }
-
- /**
- * LIKE条件
- * AND fieldName LIKE fieldValue ESCAPE escapeChar
- * 如果传入了escapeChar, 将会自动生成带ESCAPE的SQL
- * 如: andLike("code", new LikeValue('#', "%10#%"));表示查找以10%结尾的数据
- * 如: andLike("code", new LikeValue("%HOT%COOL%"));表示查找含有HOT和COOL的数据
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值 (带escapeChar和通配符的LikeValue)
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andLike(String fieldName, LikeValue fieldValue) {
- return this.and(fieldName, "like", fieldValue);
- }
-
- /**
- * NOT LIKE条件
- * [ORACLE/DB2] AND fieldName NOT LIKE('%'||fieldValue||'%')
- * [MYSQL] AND fieldName NOT LIKE CONCAT('%',fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不包含%的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andNotLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andNotLike(String, LikeValue)
- */
- public DbWhere andNotLike(String fieldName, String fieldValue) {
- return this.and(fieldName, "not like", fieldValue);
- }
-
- /**
- * NOT LIKE条件
- * AND fieldName NOT LIKE fieldValue ESCAPE escapeChar
- * 如果传入了escapeChar, 将会自动生成带ESCAPE的SQL
- * 如: andNotLike("code", new LikeValue('#', "%10#%"));表示查找不以10%结尾的数据
- * 如: andNotLike("code", new LikeValue("%HOT%COOL%"));表示查找不含有HOT和COOL的数据
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值 (带escapeChar和通配符的LikeValue)
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotLike(String fieldName, LikeValue fieldValue) {
- return this.and(fieldName, "not like", fieldValue);
- }
-
- /**
- * LIKE前缀查询条件
- * [ORACLE/DB2] AND fieldName LIKE(fieldValue||'%')
- * [MYSQL] AND fieldName LIKE CONCAT(fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找以%开头的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andLike(String, LikeValue)
- */
- public DbWhere andStarts(String fieldName, String fieldValue) {
- return this.and(fieldName, "starts", fieldValue);
- }
-
- /**
- * NOT LIKE前缀查询条件
- * [ORACLE/DB2] AND fieldName NOT LIKE(fieldValue||'%')
- * [MYSQL] AND fieldName NOT LIKE CONCAT(fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不以%开头的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andNotLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andNotLike(String, LikeValue)
- */
- public DbWhere andNotStarts(String fieldName, String fieldValue) {
- return this.and(fieldName, "not starts", fieldValue);
- }
-
- /**
- * LIKE后缀查询条件
- * [ORACLE/DB2] AND fieldName LIKE('%'||fieldValue)
- * [MYSQL] AND fieldName LIKE CONCAT('%',fieldValue)
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找以%结尾的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andLike(String, LikeValue)
- */
- public DbWhere andEnds(String fieldName, String fieldValue) {
- return this.and(fieldName, "ends", fieldValue);
- }
-
- /**
- * NOT LIKE后缀查询条件
- * [ORACLE/DB2] AND fieldName NOT LIKE('%'||fieldValue)
- * [MYSQL] AND fieldName NOT LIKE CONCAT('%',fieldValue)
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不以%结尾的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andNotLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andNotLike(String, LikeValue)
- */
- public DbWhere andNotEnds(String fieldName, String fieldValue) {
- return this.and(fieldName, "not ends", fieldValue);
- }
-
- /**
- * IN查询条件
- * [SQL] AND fieldName IN (fieldValue1, fieldValue2, ...)
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andIn(String fieldName, Collection> fieldValue) {
- return this.and(fieldName, "in", fieldValue);
- }
-
- /**
- * IN查询条件
- * [SQL] AND fieldName IN (fieldValue1, fieldValue2, ...)
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andIn(String fieldName, Object... fieldValue) {
- return this.and(fieldName, "in", fieldValue);
- }
-
- /**
- * NOT IN查询条件
- * [SQL] AND fieldName NOT IN (fieldValue1, fieldValue2, ...)
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotIn(String fieldName, Collection> fieldValue) {
- return this.and(fieldName, "not in", fieldValue);
- }
-
- /**
- * NOT IN查询条件
- * [SQL] AND fieldName NOT IN (fieldValue1, fieldValue2, ...)
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotIn(String fieldName, Object... fieldValue) {
- return this.and(fieldName, "not in", fieldValue);
- }
-
- /**
- * BETWEEN查询条件
- * [SQL] AND fieldName BETWEEN startValue AND endValue
- *
- * @param fieldName 字段名
- * @param startValue 开始字段值
- * @param endValue 结束字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andBetween(String fieldName, Object startValue, Object endValue) {
- return this.and(fieldName, "between", startValue, endValue);
- }
-
- /**
- * NOT BETWEEN查询条件
- * [SQL] AND fieldName NOT BETWEEN startValue AND endValue
- *
- * @param fieldName 字段名
- * @param startValue 开始字段值
- * @param endValue 结束字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotBetween(String fieldName, Object startValue, Object endValue) {
- return this.and(fieldName, "not between", startValue, endValue);
- }
-
- /**
- * 子查询条件
- // [SQL] AND ( USER_NAME LIKE '%'||keyword||'%' OR REAL_NAME LIKE '%'||keyword||'%' )
- where.andSubCondition(new SubCondition() { // 子条件
- public void build(DbWhere w) {
- w.orLike("userName", entity.getKeyword())
- .orLike("realName", entity.getKeyword());
- }
- });
- // JDK8
- where.andSubCondition((w) -> { // 子条件
- w.orLike("userName", entity.getKeyword())
- .orLike("realName", entity.getKeyword());
- });
- *
- * @param condition 条件构造器
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andSubCondition(SubCondition condition) {
- SubWhere where = new SubWhere(this, LogicType.AND, MatchType.Positive);
- this.put(where);
- condition.build(where);
- return this;
- }
-
- /**
- * 否定子查询条件
- // [SQL] AND NOT ( USER_NAME LIKE '%'||keyword||'%' OR REAL_NAME LIKE '%'||keyword||'%' )
- where.andNotSubCondition(new SubCondition() { // 子条件
- public void build(DbWhere w) {
- w.orLike("userName", entity.getKeyword())
- .orLike("realName", entity.getKeyword());
- }
- });
- // JDK8
- where.andNotSubCondition((w) -> { // 子条件
- w.orLike("userName", entity.getKeyword())
- .orLike("realName", entity.getKeyword());
- });
- *
- * @param condition 条件构造器
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotSubCondition(SubCondition condition) {
- SubWhere where = new SubWhere(this, LogicType.AND, MatchType.Negative);
- this.put(where);
- condition.build(where);
- return this;
- }
-
- /**
- * 自定义查询条件
- *
- * @param condition 条件对象
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andBizCondition(WhereCondition condition) {
- BizCondition bizCondition = new BizCondition(condition, LogicType.AND, MatchType.Positive);
- super.put(bizCondition);
- return this;
- }
-
- /**
- * 自定义查询条件
- *
- * @param condition 条件对象
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotBizCondition(WhereCondition condition) {
- BizCondition bizCondition = new BizCondition(condition, LogicType.AND, MatchType.Negative);
- super.put(bizCondition);
- return this;
- }
-
- /**
- * 等于条件
- * [SQL] OR fieldName = fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orEquals(String fieldName, Object fieldValue) {
- return this.or(fieldName, "=", fieldValue);
- }
-
- /**
- * 不等于条件
- * [SQL] OR fieldName != fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orNotEquals(String fieldName, Object fieldValue) {
- return this.or(fieldName, "!=", fieldValue);
- }
-
- /**
- * 小于条件
- * [SQL] OR fieldName < fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orLessThen(String fieldName, Object fieldValue) {
- return this.or(fieldName, "<", fieldValue);
- }
-
- /**
- * 小于等于条件
- * [SQL] OR fieldName <= fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orLessEqualsThen(String fieldName, Object fieldValue) {
- return this.or(fieldName, "<=", fieldValue);
- }
-
- /**
- * 大于条件
- * [SQL] OR fieldName > fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orGreaterThen(String fieldName, Object fieldValue) {
- return this.or(fieldName, ">", fieldValue);
- }
-
- /**
- * 大于等于条件
- * [SQL] OR fieldName >= fieldValue
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orGreaterEqualsThen(String fieldName, Object fieldValue) {
- return this.or(fieldName, ">=", fieldValue);
- }
-
- /**
- * IS NULL条件
- * [SQL] OR fieldName IS NULL
- *
- * @param fieldName 字段名
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orIsNull(String fieldName) {
- return this.or(fieldName, "is null");
- }
-
- /**
- * IS NOT NULL条件
- * [SQL] OR fieldName IS NOT NULL
- *
- * @param fieldName 字段名
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orIsNotNull(String fieldName) {
- return this.or(fieldName, "is not null");
- }
-
- /**
- * LIKE条件
- * [ORACLE/DB2] OR fieldName LIKE('%'||fieldValue||'%')
- * [MYSQL] OR fieldName LIKE CONCAT('%',fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找带有%的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orLike(String, LikeValue)
- */
- public DbWhere orLike(String fieldName, String fieldValue) {
- return this.or(fieldName, "like", fieldValue);
- }
-
- /**
- * LIKE条件
- * OR fieldName LIKE fieldValue ESCAPE escapeChar
- * 如果传入了escapeChar, 将会自动生成带ESCAPE的SQL
- * 如: orLike("code", new LikeValue('#', "%10#%"));表示查找以10%结尾的数据
- * 如: orLike("code", new LikeValue("%HOT%COOL%"));表示查找含有HOT和COOL的数据
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值 (带escapeChar和通配符的LikeValue)
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orLike(String fieldName, LikeValue fieldValue) {
- return this.or(fieldName, "like", fieldValue);
- }
-
- /**
- * NOT LIKE条件
- * [ORACLE/DB2] OR fieldName NOT LIKE('%'||fieldValue||'%')
- * [MYSQL] OR fieldName NOT LIKE CONCAT('%',fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不包含%的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orNotLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orNotLike(String, LikeValue)
- */
- public DbWhere orNotLike(String fieldName, String fieldValue) {
- return this.or(fieldName, "not like", fieldValue);
- }
-
- /**
- * NOT LIKE条件
- * OR fieldName NOT LIKE fieldValue ESCAPE escapeChar
- * 如果传入了escapeChar, 将会自动生成带ESCAPE的SQL
- * 如: orNotLike("code", new LikeValue('#', "%10#%"));表示查找不以10%结尾的数据
- * 如: orNotLike("code", new LikeValue("%HOT%COOL%"));表示查找不含有HOT和COOL的数据
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值 (带escapeChar和通配符的LikeValue)
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orNotLike(String fieldName, LikeValue fieldValue) {
- return this.or(fieldName, "not like", fieldValue);
- }
-
- /**
- * LIKE前缀查询条件
- * [ORACLE/DB2] OR fieldName LIKE(fieldValue||'%')
- * [MYSQL] OR fieldName LIKE CONCAT(fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找以%开头的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orLike(String, LikeValue)
- */
- public DbWhere orStarts(String fieldName, String fieldValue) {
- return this.or(fieldName, "starts", fieldValue);
- }
-
- /**
- * NOT LIKE前缀查询条件
- * [ORACLE/DB2] OR fieldName NOT LIKE(fieldValue||'%')
- * [MYSQL] OR fieldName NOT LIKE CONCAT(fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不以%开头的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orNotLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orNotLike(String, LikeValue)
- */
- public DbWhere orNotStarts(String fieldName, String fieldValue) {
- return this.or(fieldName, "not starts", fieldValue);
- }
-
- /**
- * LIKE后缀查询条件
- * [ORACLE/DB2] OR fieldName LIKE('%'||fieldValue)
- * [MYSQL] OR fieldName LIKE CONCAT('%',fieldValue)
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找以%结尾的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orLike(String, LikeValue)
- */
- public DbWhere orEnds(String fieldName, String fieldValue) {
- return this.or(fieldName, "ends", fieldValue);
- }
-
- /**
- * NOT LIKE后缀查询条件
- * [ORACLE/DB2] OR fieldName NOT LIKE('%'||fieldValue)
- * [MYSQL] OR fieldName NOT LIKE CONCAT('%',fieldValue)
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不以%结尾的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orNotLike(String, LikeValue)}方法
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orNotLike(String, LikeValue)
- */
- public DbWhere orNotEnds(String fieldName, String fieldValue) {
- return this.or(fieldName, "not ends", fieldValue);
- }
-
- /**
- * IN查询条件
- * [SQL] OR fieldName IN (fieldValue1, fieldValue2, ...)
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orIn(String fieldName, Collection> fieldValue) {
- return this.or(fieldName, "in", fieldValue);
- }
-
- /**
- * IN查询条件
- * [SQL] OR fieldName IN (fieldValue1, fieldValue2, ...)
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orIn(String fieldName, Object... fieldValue) {
- return this.or(fieldName, "in", fieldValue);
- }
-
- /**
- * NOT IN查询条件
- * [SQL] OR fieldName NOT IN (fieldValue1, fieldValue2, ...)
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orNotIn(String fieldName, Collection> fieldValue) {
- return this.or(fieldName, "not in", fieldValue);
- }
-
- /**
- * NOT IN查询条件
- * [SQL] OR fieldName NOT IN (fieldValue1, fieldValue2, ...)
- *
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orNotIn(String fieldName, Object... fieldValue) {
- return this.or(fieldName, "not in", fieldValue);
- }
-
- /**
- * BETWEEN查询条件
- * [SQL] OR fieldName BETWEEN startValue AND endValue
- *
- * @param fieldName 字段名
- * @param startValue 开始字段值
- * @param endValue 结束字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orBetween(String fieldName, Object startValue, Object endValue) {
- return this.or(fieldName, "between", startValue, endValue);
- }
-
- /**
- * NOT BETWEEN查询条件
- * [SQL] OR fieldName NOT BETWEEN startValue AND endValue
- *
- * @param fieldName 字段名
- * @param startValue 开始字段值
- * @param endValue 结束字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orNotBetween(String fieldName, Object startValue, Object endValue) {
- return this.or(fieldName, "not between", startValue, endValue);
- }
-
- /**
- * 子查询条件
- // [SQL] OR ( USER_NAME LIKE '%'||keyword||'%' OR REAL_NAME LIKE '%'||keyword||'%' )
- where.orSubCondition(new SubCondition() { // 子条件
- public void build(DbWhere w) {
- w.orLike("userName", entity.getKeyword())
- .orLike("realName", entity.getKeyword());
- }
- });
- // JDK8
- where.orSubCondition((w) -> { // 子条件
- w.orLike("userName", entity.getKeyword())
- .orLike("realName", entity.getKeyword());
- });
- *
- * @param condition 条件构造器
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orSubCondition(SubCondition condition) {
- SubWhere where = new SubWhere(this, LogicType.OR, MatchType.Positive);
- this.put(where);
- condition.build(where);
- return this;
- }
-
- /**
- * 否定子查询条件
- // [SQL] OR NOT ( USER_NAME LIKE '%'||keyword||'%' OR REAL_NAME LIKE '%'||keyword||'%' )
- where.orNotSubCondition(new SubCondition() { // 子条件
- public void build(DbWhere w) {
- w.orLike("userName", entity.getKeyword())
- .orLike("realName", entity.getKeyword());
- }
- });
- // JDK8
- where.orNotSubCondition((w) -> { // 子条件
- w.orLike("userName", entity.getKeyword())
- .orLike("realName", entity.getKeyword());
- });
- *
- * @param condition 条件构造器
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orNotSubCondition(SubCondition condition) {
- SubWhere where = new SubWhere(this, LogicType.OR, MatchType.Negative);
- this.put(where);
- condition.build(where);
- return this;
- }
-
- /**
- * 自定义查询条件
- *
- * @param condition 条件对象
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orBizCondition(WhereCondition condition) {
- BizCondition bizCondition = new BizCondition(condition, LogicType.OR, MatchType.Positive);
- super.put(bizCondition);
- return this;
- }
-
- /**
- * 自定义查询条件
- *
- * @param condition 条件对象
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orNotBizCondition(WhereCondition condition) {
- BizCondition bizCondition = new BizCondition(condition, LogicType.OR, MatchType.Negative);
- super.put(bizCondition);
- return this;
- }
-
- /**
- * 等于条件
- * [SQL] AND fieldName = fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andEqualsIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.andIf(asserts, fieldName, "=", fieldValue);
- }
-
- /**
- * 不等于条件
- * [SQL] AND fieldName != fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotEqualsIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.andIf(asserts, fieldName, "!=", fieldValue);
- }
-
- /**
- * 小于条件
- * [SQL] AND fieldName < fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andLessThenIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.andIf(asserts, fieldName, "<", fieldValue);
- }
-
- /**
- * 小于等于条件
- * [SQL] AND fieldName <= fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andLessEqualsThenIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.andIf(asserts, fieldName, "<=", fieldValue);
- }
-
- /**
- * 大于条件
- * [SQL] AND fieldName > fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andGreaterThenIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.andIf(asserts, fieldName, ">", fieldValue);
- }
-
- /**
- * 大于等于条件
- * [SQL] AND fieldName >= fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andGreaterEqualsThenIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.andIf(asserts, fieldName, ">=", fieldValue);
- }
-
- /**
- * IS NULL条件
- * [SQL] AND fieldName IS NULL
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andIsNullIf(boolean asserts, String fieldName) {
- return this.andIf(asserts, fieldName, "is null");
- }
-
- /**
- * IS NOT NULL条件
- * [SQL] AND fieldName IS NOT NULL
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andIsNotNullIf(boolean asserts, String fieldName) {
- return this.andIf(asserts, fieldName, "is not null");
- }
-
- /**
- * LIKE条件
- * [ORACLE/DB2] AND fieldName LIKE('%'||fieldValue||'%')
- * [MYSQL] AND fieldName LIKE CONCAT('%',fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找带有%的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andLikeIf(String, LikeValue)
- */
- public DbWhere andLikeIf(boolean asserts, String fieldName, String fieldValue) {
- return this.andIf(asserts, fieldName, "like", fieldValue);
- }
-
- /**
- * LIKE条件
- * AND fieldName LIKE fieldValue ESCAPE escapeChar
- * 如果传入了escapeChar, 将会自动生成带ESCAPE的SQL
- * 如: andLike("code", new LikeValue('#', "%10#%"));表示查找以10%结尾的数据
- * 如: andLike("code", new LikeValue("%HOT%COOL%"));表示查找含有HOT和COOL的数据
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值 (带escapeChar和通配符的LikeValue)
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andLikeIf(boolean asserts, String fieldName, LikeValue fieldValue) {
- return this.andIf(asserts, fieldName, "like", fieldValue);
- }
-
- /**
- * NOT LIKE条件
- * [ORACLE/DB2] AND fieldName NOT LIKE('%'||fieldValue||'%')
- * [MYSQL] AND fieldName NOT LIKE CONCAT('%',fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不包含%的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andNotLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andNotLikeIf(String, LikeValue)
- */
- public DbWhere andNotLikeIf(boolean asserts, String fieldName, String fieldValue) {
- return this.andIf(asserts, fieldName, "not like", fieldValue);
- }
-
- /**
- * NOT LIKE条件
- * AND fieldName NOT LIKE fieldValue ESCAPE escapeChar
- * 如果传入了escapeChar, 将会自动生成带ESCAPE的SQL
- * 如: andNotLike("code", new LikeValue('#', "%10#%"));表示查找不以10%结尾的数据
- * 如: andNotLike("code", new LikeValue("%HOT%COOL%"));表示查找不含有HOT和COOL的数据
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值 (带escapeChar和通配符的LikeValue)
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotLikeIf(boolean asserts, String fieldName, LikeValue fieldValue) {
- return this.andIf(asserts, fieldName, "not like", fieldValue);
- }
-
- /**
- * LIKE前缀查询条件
- * [ORACLE/DB2] AND fieldName LIKE(fieldValue||'%')
- * [MYSQL] AND fieldName LIKE CONCAT(fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找以%开头的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andLikeIf(String, LikeValue)
- */
- public DbWhere andStartsIf(boolean asserts, String fieldName, String fieldValue) {
- return this.andIf(asserts, fieldName, "starts", fieldValue);
- }
-
- /**
- * NOT LIKE前缀查询条件
- * [ORACLE/DB2] AND fieldName NOT LIKE(fieldValue||'%')
- * [MYSQL] AND fieldName NOT LIKE CONCAT(fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不以%开头的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andNotLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andNotLikeIf(String, LikeValue)
- */
- public DbWhere andNotStartsIf(boolean asserts, String fieldName, String fieldValue) {
- return this.andIf(asserts, fieldName, "not starts", fieldValue);
- }
-
- /**
- * LIKE后缀查询条件
- * [ORACLE/DB2] AND fieldName LIKE('%'||fieldValue)
- * [MYSQL] AND fieldName LIKE CONCAT('%',fieldValue)
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找以%结尾的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andLikeIf(String, LikeValue)
- */
- public DbWhere andEndsIf(boolean asserts, String fieldName, String fieldValue) {
- return this.andIf(asserts, fieldName, "ends", fieldValue);
- }
-
- /**
- * NOT LIKE后缀查询条件
- * [ORACLE/DB2] AND fieldName NOT LIKE('%'||fieldValue)
- * [MYSQL] AND fieldName NOT LIKE CONCAT('%',fieldValue)
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不以%结尾的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #andNotLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #andNotLikeIf(String, LikeValue)
- */
- public DbWhere andNotEndsIf(boolean asserts, String fieldName, String fieldValue) {
- return this.andIf(asserts, fieldName, "not ends", fieldValue);
- }
-
- /**
- * IN查询条件
- * [SQL] AND fieldName IN (fieldValue1, fieldValue2, ...)
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andInIf(boolean asserts, String fieldName, Collection> fieldValue) {
- return this.andIf(asserts, fieldName, "in", fieldValue);
- }
-
- /**
- * IN查询条件
- * [SQL] AND fieldName IN (fieldValue1, fieldValue2, ...)
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andInIf(boolean asserts, String fieldName, Object... fieldValue) {
- return this.andIf(asserts, fieldName, "in", fieldValue);
- }
-
- /**
- * NOT IN查询条件
- * [SQL] AND fieldName NOT IN (fieldValue1, fieldValue2, ...)
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotInIf(boolean asserts, String fieldName, Collection> fieldValue) {
- return this.andIf(asserts, fieldName, "not in", fieldValue);
- }
-
- /**
- * NOT IN查询条件
- * [SQL] AND fieldName NOT IN (fieldValue1, fieldValue2, ...)
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotInIf(boolean asserts, String fieldName, Object... fieldValue) {
- return this.andIf(asserts, fieldName, "not in", fieldValue);
- }
-
- /**
- * BETWEEN查询条件
- * [SQL] AND fieldName BETWEEN startValue AND endValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param startValue 开始字段值
- * @param endValue 结束字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andBetweenIf(boolean asserts, String fieldName, Object startValue, Object endValue) {
- return this.andIf(asserts, fieldName, "between", startValue, endValue);
- }
-
- /**
- * NOT BETWEEN查询条件
- * [SQL] AND fieldName NOT BETWEEN startValue AND endValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param startValue 开始字段值
- * @param endValue 结束字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere andNotBetweenIf(boolean asserts, String fieldName, Object startValue, Object endValue) {
- return this.andIf(asserts, fieldName, "not between", startValue, endValue);
- }
-
- /**
- * 等于条件
- * [SQL] OR fieldName = fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orEqualsIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.orIf(asserts, fieldName, "=", fieldValue);
- }
-
- /**
- * 不等于条件
- * [SQL] OR fieldName != fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orNotEqualsIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.orIf(asserts, fieldName, "!=", fieldValue);
- }
-
- /**
- * 小于条件
- * [SQL] OR fieldName < fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orLessThenIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.orIf(asserts, fieldName, "<", fieldValue);
- }
-
- /**
- * 小于等于条件
- * [SQL] OR fieldName <= fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orLessEqualsThenIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.orIf(asserts, fieldName, "<=", fieldValue);
- }
-
- /**
- * 大于条件
- * [SQL] OR fieldName > fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orGreaterThenIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.orIf(asserts, fieldName, ">", fieldValue);
- }
-
- /**
- * 大于等于条件
- * [SQL] OR fieldName >= fieldValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orGreaterEqualsThenIf(boolean asserts, String fieldName, Object fieldValue) {
- return this.orIf(asserts, fieldName, ">=", fieldValue);
- }
-
- /**
- * IS NULL条件
- * [SQL] OR fieldName IS NULL
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orIsNullIf(boolean asserts, String fieldName) {
- return this.orIf(asserts, fieldName, "is null");
- }
-
- /**
- * IS NOT NULL条件
- * [SQL] OR fieldName IS NOT NULL
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orIsNotNullIf(boolean asserts, String fieldName) {
- return this.orIf(asserts, fieldName, "is not null");
- }
-
- /**
- * LIKE条件
- * [ORACLE/DB2] OR fieldName LIKE('%'||fieldValue||'%')
- * [MYSQL] OR fieldName LIKE CONCAT('%',fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找带有%的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orLikeIf(String, LikeValue)
- */
- public DbWhere orLikeIf(boolean asserts, String fieldName, String fieldValue) {
- return this.orIf(asserts, fieldName, "like", fieldValue);
- }
-
- /**
- * LIKE条件
- * OR fieldName LIKE fieldValue ESCAPE escapeChar
- * 如果传入了escapeChar, 将会自动生成带ESCAPE的SQL
- * 如: orLike("code", new LikeValue('#', "%10#%"));表示查找以10%结尾的数据
- * 如: orLike("code", new LikeValue("%HOT%COOL%"));表示查找含有HOT和COOL的数据
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值 (带escapeChar和通配符的LikeValue)
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orLikeIf(boolean asserts, String fieldName, LikeValue fieldValue) {
- return this.orIf(asserts, fieldName, "like", fieldValue);
- }
-
- /**
- * NOT LIKE条件
- * [ORACLE/DB2] OR fieldName NOT LIKE('%'||fieldValue||'%')
- * [MYSQL] OR fieldName NOT LIKE CONCAT('%',fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不包含%的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orNotLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orNotLikeIf(String, LikeValue)
- */
- public DbWhere orNotLikeIf(boolean asserts, String fieldName, String fieldValue) {
- return this.orIf(asserts, fieldName, "not like", fieldValue);
- }
-
- /**
- * NOT LIKE条件
- * OR fieldName NOT LIKE fieldValue ESCAPE escapeChar
- * 如果传入了escapeChar, 将会自动生成带ESCAPE的SQL
- * 如: orNotLike("code", new LikeValue('#', "%10#%"));表示查找不以10%结尾的数据
- * 如: orNotLike("code", new LikeValue("%HOT%COOL%"));表示查找不含有HOT和COOL的数据
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值 (带escapeChar和通配符的LikeValue)
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orNotLikeIf(boolean asserts, String fieldName, LikeValue fieldValue) {
- return this.orIf(asserts, fieldName, "not like", fieldValue);
- }
-
- /**
- * LIKE前缀查询条件
- * [ORACLE/DB2] OR fieldName LIKE(fieldValue||'%')
- * [MYSQL] OR fieldName LIKE CONCAT(fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找以%开头的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orLikeIf(String, LikeValue)
- */
- public DbWhere orStartsIf(boolean asserts, String fieldName, String fieldValue) {
- return this.orIf(asserts, fieldName, "starts", fieldValue);
- }
-
- /**
- * NOT LIKE前缀查询条件
- * [ORACLE/DB2] OR fieldName NOT LIKE(fieldValue||'%')
- * [MYSQL] OR fieldName NOT LIKE CONCAT(fieldValue,'%')
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不以%开头的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orNotLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orNotLikeIf(String, LikeValue)
- */
- public DbWhere orNotStartsIf(boolean asserts, String fieldName, String fieldValue) {
- return this.orIf(asserts, fieldName, "not starts", fieldValue);
- }
-
- /**
- * LIKE后缀查询条件
- * [ORACLE/DB2] OR fieldName LIKE('%'||fieldValue)
- * [MYSQL] OR fieldName LIKE CONCAT('%',fieldValue)
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找以%结尾的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orLikeIf(String, LikeValue)
- */
- public DbWhere orEndsIf(boolean asserts, String fieldName, String fieldValue) {
- return this.orIf(asserts, fieldName, "ends", fieldValue);
- }
-
- /**
- * NOT LIKE后缀查询条件
- * [ORACLE/DB2] OR fieldName NOT LIKE('%'||fieldValue)
- * [MYSQL] OR fieldName NOT LIKE CONCAT('%',fieldValue)
- * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不以%结尾的数据, 将会自动生成带ESCAPE的SQL
- * 如果希望自己处理ESCAPE逻辑, 可使用{@link #orNotLikeIf(String, LikeValue)}方法
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- * @see #orNotLikeIf(String, LikeValue)
- */
- public DbWhere orNotEndsIf(boolean asserts, String fieldName, String fieldValue) {
- return this.orIf(asserts, fieldName, "not ends", fieldValue);
+ public DbWhere() {
+ super();
}
- /**
- * IN查询条件
- * [SQL] OR fieldName IN (fieldValue1, fieldValue2, ...)
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orInIf(boolean asserts, String fieldName, Collection> fieldValue) {
- return this.orIf(asserts, fieldName, "in", fieldValue);
+ protected DbWhere(List conditions) {
+ super(conditions);
}
/**
- * IN查询条件
- * [SQL] OR fieldName IN (fieldValue1, fieldValue2, ...)
+ * 查询条件
*
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
+ * @param fieldName 字段名称
+ * @return 返回后续流式操作对象
*/
- public DbWhere orInIf(boolean asserts, String fieldName, Object... fieldValue) {
- return this.orIf(asserts, fieldName, "in", fieldValue);
+ public DbWhereForFieldCore on(String fieldName) {
+ DbWhereForStartCore start = new DbWhereForStartCore<>(this, this);
+ return new DbWhereForFieldCore<>(start, SkipType.NONE, LogicType.AND, fieldName);
}
/**
- * NOT IN查询条件
- * [SQL] OR fieldName NOT IN (fieldValue1, fieldValue2, ...)
+ * 查询条件
*
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
+ * @return 返回后续流式操作对象
*/
- public DbWhere orNotInIf(boolean asserts, String fieldName, Collection> fieldValue) {
- return this.orIf(asserts, fieldName, "not in", fieldValue);
+ public DbWhereForOnFieldless on() {
+ DbWhereForStartCore start = new DbWhereForStartCore<>(this, this);
+ return new DbWhereForOnFieldless<>(start, SkipType.NONE);
}
/**
- * NOT IN查询条件
- * [SQL] OR fieldName NOT IN (fieldValue1, fieldValue2, ...)
+ * 克隆为新对象(如果子类有新增字段或没有默认构造函数就应该覆盖该方法)
*
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param fieldValue 字段值
- * @return 返回容器自身, 用于链式操作
+ * @return 新对象
+ * @since 5.0.0
*/
- public DbWhere orNotInIf(boolean asserts, String fieldName, Object... fieldValue) {
- return this.orIf(asserts, fieldName, "not in", fieldValue);
+ @Override
+ public DbWhere copy() {
+ DbWhere copies = newCopies();
+ this.copyTo(copies);
+ return copies;
}
- /**
- * BETWEEN查询条件
- * [SQL] OR fieldName BETWEEN startValue AND endValue
- *
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param startValue 开始字段值
- * @param endValue 结束字段值
- * @return 返回容器自身, 用于链式操作
- */
- public DbWhere orBetweenIf(boolean asserts, String fieldName, Object startValue, Object endValue) {
- return this.orIf(asserts, fieldName, "between", startValue, endValue);
+ protected void copyTo(DbWhere copies) {
+ Iterator iterator = this.iterator();
+ while (iterator.hasNext()) {
+ DbCondition item = iterator.next();
+ if (item instanceof LogicField) {
+ copies.put(((LogicField) item).copy());
+ } else if (item instanceof DbField) {
+ copies.put(((DbField) item).copy());
+ } else if (item instanceof SubWhere) {
+ copies.put(((SubWhere) item).copy());
+ } else if (item instanceof DbWhere) {
+ copies.put(((DbWhere) item).copy());
+ } else if (item instanceof Copyable) {
+ DbCondition newer = (DbCondition) ((Copyable) item).copy();
+ copies.put(newer);
+ } else { // DbCondition/DbConditions
+ copies.put(item); // 无法克隆为副本
+ }
+ }
}
/**
- * NOT BETWEEN查询条件
- * [SQL] OR fieldName NOT BETWEEN startValue AND endValue
+ * 创建副本对象(如果子类没有默认构造函数就应该覆盖该方法)
*
- * @param asserts 判断条件, 只有asserts=true才添加查询条件
- * @param fieldName 字段名
- * @param startValue 开始字段值
- * @param endValue 结束字段值
- * @return 返回容器自身, 用于链式操作
+ * @return 副本对象
+ * @since 5.0.0
*/
- public DbWhere orNotBetweenIf(boolean asserts, String fieldName, Object startValue, Object endValue) {
- return this.orIf(asserts, fieldName, "not between", startValue, endValue);
- }
-
- public static interface SubCondition {
-
- void build(DbWhere where);
- }
-
- public static class BizCondition implements DbCondition, LogicCondition, MatchCondition {
-
- private final WhereCondition condition;
- /** 逻辑联连类型: AND / OR **/
- private final LogicType logicType;
- /** 匹配模式 **/
- private final MatchType matchType;
-
- public BizCondition(WhereCondition condition, LogicType logicType, MatchType matchType) {
- this.condition = condition;
- this.logicType = logicType;
- this.matchType = matchType;
- }
-
- public WhereCondition getWhereCondition() {
- return condition;
- }
-
- /** 逻辑联连类型: AND / OR **/
- @Override
- public LogicType getLogicType() {
- return logicType;
- }
-
- /** 匹配模式 **/
- @Override
- public MatchType getMatchType() {
- return matchType;
- }
-
- @Override
- public boolean isEmpty() {
- return condition == null ? true : condition.isEmpty();
+ protected DbWhere newCopies() {
+ if (this.getClass() == DbWhere.class) { // 当前类
+ return new DbWhere();
+ } else { // 子类
+ try {
+ return this.getClass().newInstance();
+ } catch (Exception e) {
+ throw new IllegalStateException("CloneNotSupported, FailedToInvokeDefaultConstructor.");
+ }
}
}
@@ -1763,123 +177,9 @@ public class DbWhere extends DbItems implements Copyable {
return instance;
}
- public class Field extends DbField implements LogicCondition {
-
- /** serialVersionUID **/
- private static final long serialVersionUID = 1L;
-
- private final DbWhere container;
- private final LogicType logicType;
-
- /** 构造函数 **/
- public Field(LogicType logicType) {
- this.logicType = logicType;
- this.container = DbWhere.this;
- }
-
- /** 构造函数 **/
- private Field(LogicType logicType, DbField field) {
- super(field.getOperateType(), field.getFieldName(), field.getFieldValue());
- this.container = DbWhere.this;
- this.logicType = logicType;
- }
-
- /** 构造函数 **/
- public Field(LogicType logicType, String fieldName, Object fieldValue) {
- super(fieldName, fieldValue);
- this.container = DbWhere.this;
- this.logicType = logicType;
- }
-
- /** 构造函数 **/
- public Field(LogicType logicType, String operateType, String fieldName, Object fieldValue) {
- super(operateType, fieldName, fieldValue);
- this.container = DbWhere.this;
- this.logicType = logicType;
- }
-
- public DbWhere getContainer() {
- return container;
- }
-
- @Override
- public LogicType getLogicType() {
- return logicType;
- }
-
- @Override
- public Field copy() {
- LogicType logicType = this.getLogicType();
- String operateType = this.getOperateType();
- String fieldName = this.getFieldName();
- Object fieldValue = this.getFieldValue();
- return new Field(logicType, operateType, fieldName, fieldValue);
- }
- }
-
- private static class InnerSubWhere extends SubWhere {
-
- /** SerialVersionUID **/
- private static final long serialVersionUID = 1L;
-
- private LogicType innerLogicType;
-
- protected InnerSubWhere() {
- super();
- }
-
- public InnerSubWhere(DbWhere parent, LogicType logicType, MatchType matchType, LogicType innerLogicType) {
- super(parent, logicType, matchType);
- this.innerLogicType = innerLogicType;
- }
-
- @Override
- public SubWhere on(String fieldName, String operate, Object... fieldValues) {
- if (innerLogicType == LogicType.OR) {
- this.or(fieldName, operate, fieldValues);
- } else {
- this.and(fieldName, operate, fieldValues);
- }
- return this;
- }
-
- /** 增加自定义条件 **/
- @Override
- public SubWhere on(WhereCondition condition) {
- if (innerLogicType == LogicType.OR) {
- super.orBizCondition(condition);
- } else {
- super.andBizCondition(condition);
- }
- return this;
- }
-
- /** {@inheritDoc} **/
- @Override
- public InnerSubWhere copy() {
- InnerSubWhere copies = newCopies();
- this.copyTo(copies);
- return copies;
- }
-
- protected void copyTo(InnerSubWhere copies) {
- super.copyTo(copies);
- copies.innerLogicType = this.innerLogicType;
- }
+ public static interface SubCondition {
- /** {@inheritDoc} **/
- @Override
- protected InnerSubWhere newCopies() {
- if (this.getClass() == InnerSubWhere.class) { // 当前类
- return new InnerSubWhere();
- } else { // 子类
- try {
- return this.getClass().newInstance();
- } catch (Exception e) {
- throw new IllegalStateException("CloneNotSupported, FailedToInvokeDefaultConstructor.");
- }
- }
- }
+ void build(DbWhere where);
}
/**
@@ -1942,11 +242,5 @@ public class DbWhere extends DbItems implements Copyable {
public void clear() {
throw new UnsupportedOperationException("read only");
}
-
- @Override
- public SubWhere sub(String operate) {
- throw new UnsupportedOperationException("read only");
- }
-
}
}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereBase.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereBase.java
new file mode 100644
index 0000000000000000000000000000000000000000..83045b61456a79e20cadd9f23ec44b8c2e9dc9a3
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereBase.java
@@ -0,0 +1,78 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+import com.gitee.qdbp.able.enums.LogicType;
+import com.gitee.qdbp.able.enums.MatchType;
+import com.gitee.qdbp.able.jdbc.base.WhereCondition;
+import com.gitee.qdbp.able.jdbc.condition.DbWhere.SubCondition;
+import com.gitee.qdbp.tools.utils.VerifyTools;
+
+/**
+ * DbField收集器
+ *
+ * @author zhaohuihua
+ * @version 20210606
+ */
+abstract class DbWhereBase {
+
+ protected T root;
+ protected DbItems items;
+
+ protected DbWhereBase(T root, DbItems items) {
+ this.root = root;
+ this.items = items;
+ }
+
+ /**
+ * 增加条件
+ *
+ * @param condition 条件
+ */
+ protected void put(DbField condition) {
+ VerifyTools.requireNonNull(condition, "condition");
+ if (condition instanceof LogicField) {
+ this.items.put(condition);
+ } else {
+ this.items.put(new LogicField(LogicType.AND, condition));
+ }
+ }
+
+ /**
+ * 增加条件
+ *
+ * @param fieldName 字段名称
+ * @param operate 操作符
+ * @param fieldValues 字段值
+ * @return 返回后续流式操作对象
+ */
+ protected void put(LogicType logicType, String fieldName, String operate, Object... fieldValues) {
+ LogicField condition = LogicField.of(logicType, fieldName, operate, fieldValues);
+ this.items.put(condition);
+ }
+
+ /**
+ * 增加子查询条件
+ *
+ * @param logicType 逻辑类型 AND还是OR
+ * @param matchType 匹配类型 正向匹配还是反向匹配
+ * @param condition 条件构造器
+ * @return 返回后续流式操作对象
+ */
+ protected void put(LogicType logicType, MatchType matchType, SubCondition condition) {
+ SubWhere where = new SubWhere(logicType, matchType);
+ condition.build(where);
+ this.items.put(where);
+ }
+
+ /**
+ * 增加自定义查询条件
+ *
+ * @param logicType 逻辑类型 AND还是OR
+ * @param matchType 匹配类型 正向匹配还是反向匹配
+ * @param condition 条件对象
+ * @return 返回后续流式操作对象
+ */
+ protected void put(LogicType logicType, MatchType matchType, WhereCondition condition) {
+ BizCondition bizCondition = new BizCondition(logicType, matchType, condition);
+ this.items.put(bizCondition);
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForFieldBase.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForFieldBase.java
new file mode 100644
index 0000000000000000000000000000000000000000..d065fd3d9ac91e45aa418fefa40b4a176093cd5b
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForFieldBase.java
@@ -0,0 +1,309 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
+import com.gitee.qdbp.able.enums.LogicType;
+import com.gitee.qdbp.able.jdbc.model.LikeValue;
+
+/**
+ * 数据库Where条件容器
+ *
+ * @author zhaohuihua
+ * @version 181221
+ */
+public class DbWhereForFieldBase extends DbWhereBase {
+
+ private DbWhereForStartCore start;
+ private SkipType skipType;
+ private LogicType logicType;
+ private String fieldName;
+
+ protected DbWhereForFieldBase(DbWhereForStartCore start, SkipType skipType, LogicType logicType,
+ String fieldName) {
+ super(start.root, start.items);
+ this.start = start;
+ this.skipType = skipType;
+ this.logicType = logicType;
+ this.fieldName = fieldName;
+ }
+
+ /**
+ * 自定义条件
+ *
+ * @param operate 操作符
+ * @param fieldValues 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore when(String operate, Object... fieldValues) {
+ return this.on(operate, fieldValues);
+ }
+
+ /**
+ * 增加条件
+ *
+ * @param operate 操作符
+ * @param fieldValues 字段值
+ * @return 返回后续流式操作对象
+ */
+ protected DbWhereForStartCore on(String operate, Object... fieldValues) {
+ if (skipType == SkipType.NONE || skipType == SkipType.BLANK_VALUE && !InnerUtils.isBlank(fieldValues)) {
+ this.put(logicType, fieldName, operate, fieldValues);
+ }
+ return start;
+ }
+
+ /**
+ * 等于条件
+ * [SQL] AND fieldName = fieldValue
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore equals(Serializable fieldValue) {
+ return this.on("=", fieldValue);
+ }
+
+ /**
+ * 不等于条件
+ * [SQL] AND fieldName != fieldValue
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore notEquals(Object fieldValue) {
+ return this.on("!=", fieldValue);
+ }
+
+ /**
+ * 小于条件
+ * [SQL] AND fieldName < fieldValue
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore lessThen(Object fieldValue) {
+ return this.on("<", fieldValue);
+ }
+
+ /**
+ * 小于等于条件
+ * [SQL] AND fieldName <= fieldValue
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore lessEqualsThen(Object fieldValue) {
+ return this.on("<=", fieldValue);
+ }
+
+ /**
+ * 大于条件
+ * [SQL] AND fieldName > fieldValue
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore greaterThen(Object fieldValue) {
+ return this.on(">", fieldValue);
+ }
+
+ /**
+ * 大于等于条件
+ * [SQL] AND fieldName >= fieldValue
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore greaterEqualsThen(Object fieldValue) {
+ return this.on(">=", fieldValue);
+ }
+
+ /**
+ * LIKE条件
+ * [ORACLE/DB2] AND fieldName LIKE('%'||fieldValue||'%')
+ * [MYSQL] AND fieldName LIKE CONCAT('%',fieldValue,'%')
+ * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找带有%的数据, 将会自动生成带ESCAPE的SQL
+ * 如果希望自己处理ESCAPE逻辑, 可使用{@link #like(LikeValue)}方法
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ * @see #like(LikeValue)
+ */
+ public DbWhereForStartCore like(String fieldValue) {
+ return this.on("like", fieldValue);
+ }
+
+ /**
+ * LIKE条件
+ * AND fieldName LIKE fieldValue ESCAPE escapeChar
+ * 如果传入了escapeChar, 将会自动生成带ESCAPE的SQL
+ * 如: andLike("code", new LikeValue('#', "%10#%"));表示查找以10%结尾的数据
+ * 如: andLike("code", new LikeValue("%HOT%COOL%"));表示查找含有HOT和COOL的数据
+ *
+ * @param fieldValue 字段值 (带escapeChar和通配符的LikeValue)
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore like(LikeValue fieldValue) {
+ return this.on("like", fieldValue);
+ }
+
+ /**
+ * NOT LIKE条件
+ * [ORACLE/DB2] AND fieldName NOT LIKE('%'||fieldValue||'%')
+ * [MYSQL] AND fieldName NOT LIKE CONCAT('%',fieldValue,'%')
+ * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不包含%的数据, 将会自动生成带ESCAPE的SQL
+ * 如果希望自己处理ESCAPE逻辑, 可使用{@link #notLike(LikeValue)}方法
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ * @see #notLike(LikeValue)
+ */
+ public DbWhereForStartCore notLike(String fieldValue) {
+ return this.on("not like", fieldValue);
+ }
+
+ /**
+ * NOT LIKE条件
+ * AND fieldName NOT LIKE fieldValue ESCAPE escapeChar
+ * 如果传入了escapeChar, 将会自动生成带ESCAPE的SQL
+ * 如: andNotLike("code", new LikeValue('#', "%10#%"));表示查找不以10%结尾的数据
+ * 如: andNotLike("code", new LikeValue("%HOT%COOL%"));表示查找不含有HOT和COOL的数据
+ *
+ * @param fieldValue 字段值 (带escapeChar和通配符的LikeValue)
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore notLike(LikeValue fieldValue) {
+ return this.on("not like", fieldValue);
+ }
+
+ /**
+ * LIKE前缀查询条件
+ * [ORACLE/DB2] AND fieldName LIKE(fieldValue||'%')
+ * [MYSQL] AND fieldName LIKE CONCAT(fieldValue,'%')
+ * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找以%开头的数据, 将会自动生成带ESCAPE的SQL
+ * 如果希望自己处理ESCAPE逻辑, 可使用{@link #like(LikeValue)}方法
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ * @see #like(LikeValue)
+ */
+ public DbWhereForStartCore startsWith(String fieldValue) {
+ return this.on("starts", fieldValue);
+ }
+
+ /**
+ * NOT LIKE前缀查询条件
+ * [ORACLE/DB2] AND fieldName NOT LIKE(fieldValue||'%')
+ * [MYSQL] AND fieldName NOT LIKE CONCAT(fieldValue,'%')
+ * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不以%开头的数据, 将会自动生成带ESCAPE的SQL
+ * 如果希望自己处理ESCAPE逻辑, 可使用{@link #notLike(LikeValue)}方法
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ * @see #notLike(LikeValue)
+ */
+ public DbWhereForStartCore notStartsWith(String fieldValue) {
+ return this.on("not starts", fieldValue);
+ }
+
+ /**
+ * LIKE后缀查询条件
+ * [ORACLE/DB2] AND fieldName LIKE('%'||fieldValue)
+ * [MYSQL] AND fieldName LIKE CONCAT('%',fieldValue)
+ * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找以%结尾的数据, 将会自动生成带ESCAPE的SQL
+ * 如果希望自己处理ESCAPE逻辑, 可使用{@link #like(LikeValue)}方法
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ * @see #like(LikeValue)
+ */
+ public DbWhereForStartCore endsWith(String fieldValue) {
+ return this.on("ends", fieldValue);
+ }
+
+ /**
+ * NOT LIKE后缀查询条件
+ * [ORACLE/DB2] AND fieldName NOT LIKE('%'||fieldValue)
+ * [MYSQL] AND fieldName NOT LIKE CONCAT('%',fieldValue)
+ * 如果fieldValue中包含%等特殊字符, 只会当作普通字符处理, 就表示查找不以%结尾的数据, 将会自动生成带ESCAPE的SQL
+ * 如果希望自己处理ESCAPE逻辑, 可使用{@link #notLike(LikeValue)}方法
+ *
+ * @param fieldValue 字段值
+ * @return 返回后续流式操作对象
+ * @see #notLike(LikeValue)
+ */
+ public DbWhereForStartCore notEndsWith(String fieldValue) {
+ return this.on("not ends", fieldValue);
+ }
+
+ /**
+ * IN查询条件
+ * [SQL] AND fieldName IN (fieldValue1, fieldValue2, ...)
+ *
+ * @param fieldValues 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore in(Collection extends Serializable> fieldValues) {
+ return this.on("in", fieldValues);
+ }
+
+ /**
+ * IN查询条件
+ * [SQL] AND fieldName IN (fieldValue1, fieldValue2, ...)
+ *
+ * @param fieldValues 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore in(Serializable... fieldValues) {
+ return this.on("in", Arrays.asList(fieldValues));
+ }
+
+ /**
+ * NOT IN查询条件
+ * [SQL] AND fieldName NOT IN (fieldValue1, fieldValue2, ...)
+ *
+ * @param fieldValues 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore notIn(Collection extends Serializable> fieldValues) {
+ return this.on("not in", fieldValues);
+ }
+
+ /**
+ * NOT IN查询条件
+ * [SQL] AND fieldName NOT IN (fieldValue1, fieldValue2, ...)
+ *
+ * @param fieldValues 字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore notIn(Serializable... fieldValues) {
+ return this.on("not in", Arrays.asList(fieldValues));
+ }
+
+ /**
+ * BETWEEN查询条件
+ * [SQL] AND fieldName BETWEEN startValue AND endValue
+ * 在常见数据库中, BETWEEN是包含两端的, 即 fieldName>=startValue AND fieldName<=endValue
+ *
+ * @param startValue 开始字段值
+ * @param endValue 结束字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore between(Serializable startValue, Serializable endValue) {
+ return this.on("between", startValue, endValue);
+ }
+
+ /**
+ * NOT BETWEEN查询条件
+ * [SQL] AND fieldName NOT BETWEEN startValue AND endValue
+ *
+ * @param startValue 开始字段值
+ * @param endValue 结束字段值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore notBetween(Serializable startValue, Serializable endValue) {
+ return this.on("not between", startValue, endValue);
+ }
+
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForFieldCore.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForFieldCore.java
new file mode 100644
index 0000000000000000000000000000000000000000..269c898853b8b4d18814c780a56484da64e5f683
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForFieldCore.java
@@ -0,0 +1,37 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+import com.gitee.qdbp.able.enums.LogicType;
+
+/**
+ * 数据库Where条件容器
+ *
+ * @author zhaohuihua
+ * @version 181221
+ */
+public class DbWhereForFieldCore extends DbWhereForFieldBase {
+
+ public DbWhereForFieldCore(DbWhereForStartCore parent, SkipType skipType, LogicType logicType, String fieldName) {
+ super(parent, skipType, logicType, fieldName);
+ }
+
+ /**
+ * IS NULL条件
+ * [SQL] AND fieldName IS NULL
+ *
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore isNull() {
+ return this.on("is null");
+ }
+
+ /**
+ * IS NOT NULL条件
+ * [SQL] AND fieldName IS NOT NULL
+ *
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore isNotNull() {
+ return this.on("is not null");
+ }
+
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForFieldless.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForFieldless.java
new file mode 100644
index 0000000000000000000000000000000000000000..31b62c77dc0a23f21ac2dc3bfcde1f6ee7754cfb
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForFieldless.java
@@ -0,0 +1,120 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+import com.gitee.qdbp.able.enums.LogicType;
+import com.gitee.qdbp.able.enums.MatchType;
+import com.gitee.qdbp.able.jdbc.base.WhereCondition;
+import com.gitee.qdbp.able.jdbc.condition.DbWhere.SubCondition;
+
+/**
+ * 数据库Where条件容器
+ *
+ * @author zhaohuihua
+ * @version 181221
+ */
+public class DbWhereForFieldless extends DbWhereBase {
+
+ protected DbWhereForStartCore start;
+ protected SkipType skipType;
+ protected LogicType logicType;
+
+ protected DbWhereForFieldless(DbWhereForStartCore start, SkipType skipType, LogicType logicType) {
+ super(start.root, start.items);
+ this.start = start;
+ this.skipType = skipType;
+ this.logicType = logicType;
+ }
+
+ /**
+ * 子查询条件
+ *
+ * @param logicType 逻辑类型 AND还是OR
+ * @param matchType 匹配类型 正向匹配还是反向匹配
+ * @param condition 条件构造器
+ * @return 返回后续流式操作对象
+ */
+ protected DbWhereForStartCore on(MatchType matchType, SubCondition condition) {
+ if (skipType == SkipType.NONE || skipType == SkipType.BLANK_VALUE && condition != null) {
+ this.put(logicType, matchType, condition);
+ }
+ return start;
+ }
+
+ /**
+ * 自定义查询条件
+ *
+ * @param condition 条件对象
+ * @param logicType 逻辑类型 AND还是OR
+ * @param matchType 匹配类型 正向匹配还是反向匹配
+ * @return 返回后续流式操作对象
+ */
+ protected DbWhereForStartCore on(MatchType matchType, WhereCondition condition) {
+ if (skipType == SkipType.NONE || skipType == SkipType.BLANK_VALUE && condition != null) {
+ this.put(logicType, matchType, condition);
+ }
+ return start;
+ }
+
+ /**
+ * 子查询条件
+ // [SQL] AND ( USER_NAME LIKE '%'||keyword||'%' OR REAL_NAME LIKE '%'||keyword||'%' )
+ where.and().subCondition(new SubCondition() { // 子条件
+ public void build(DbWhere w) {
+ w.on("userName").like(entity.getKeyword())
+ .or("realName").like(entity.getKeyword());
+ }
+ });
+ // JDK8
+ where.and().subCondition((w) -> { // 子条件
+ w.on("userName").like(entity.getKeyword())
+ .or("realName").like(entity.getKeyword());
+ });
+ *
+ * @param condition 条件构造器
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore subCondition(SubCondition condition) {
+ return this.on(MatchType.Positive, condition);
+ }
+
+ /**
+ * 否定子查询条件
+ // [SQL] AND NOT ( USER_NAME LIKE '%'||keyword||'%' OR REAL_NAME LIKE '%'||keyword||'%' )
+ where.and().notSubCondition(new SubCondition() { // 子条件
+ public void build(DbWhere w) {
+ w.on("userName").like(entity.getKeyword())
+ .or("realName").like(entity.getKeyword());
+ }
+ });
+ // JDK8
+ where.and().notSubCondition((w) -> { // 子条件
+ w.onLike("userName", entity.getKeyword())
+ .orLike("realName", entity.getKeyword());
+ });
+ *
+ * @param condition 条件构造器
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore notSubCondition(SubCondition condition) {
+ return this.on(MatchType.Negative, condition);
+ }
+
+ /**
+ * 自定义查询条件
+ *
+ * @param condition 条件对象
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore bizCondition(WhereCondition condition) {
+ return this.on(MatchType.Positive, condition);
+ }
+
+ /**
+ * 自定义查询条件
+ *
+ * @param condition 条件对象
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartCore notBizCondition(WhereCondition condition) {
+ return this.on(MatchType.Negative, condition);
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForOnFieldless.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForOnFieldless.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0a5224ac79bc7baed79c913474c07e2b5616fb5
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForOnFieldless.java
@@ -0,0 +1,65 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+import com.gitee.qdbp.able.enums.LogicType;
+
+/**
+ * 数据库Where条件容器
+ *
+ * @author zhaohuihua
+ * @version 181221
+ */
+public class DbWhereForOnFieldless extends DbWhereForFieldless {
+
+ public DbWhereForOnFieldless(DbWhereForStartCore start, SkipType skipType) {
+ super(start, skipType, LogicType.AND);
+ }
+
+ /**
+ * AND查询条件
+ *
+ * @param fieldName 字段名称
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForFieldCore and(String fieldName) {
+ return new DbWhereForFieldCore(start, skipType, LogicType.AND, fieldName);
+ }
+
+ /**
+ * OR查询条件
+ *
+ * @param fieldName 字段名称
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForFieldCore or(String fieldName) {
+ return new DbWhereForFieldCore(start, skipType, LogicType.OR, fieldName);
+ }
+
+ /**
+ * 只有当判断条件为true时才添加查询条件
+ *
+ * @param ifValue 判断条件
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartContinue ifTrue(boolean ifValue) {
+ return new DbWhereForStartContinue(start, ifValue ? SkipType.NONE : SkipType.SKIP);
+ }
+
+ /**
+ * 只有当目标值不为空时才添加查询条件
+ *
+ * @param value 目标值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartContinue ifHasValue(Object value) {
+ return new DbWhereForStartContinue<>(start, InnerUtils.isBlank(value) ? SkipType.SKIP : SkipType.NONE);
+ }
+
+ /**
+ * 只有当字段值不为空时才添加查询条件
+ *
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartByField ifHasValue() {
+ return new DbWhereForStartByField<>(start, SkipType.BLANK_VALUE);
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartAbstract.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartAbstract.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e44f420c591a162beba96051f9de43b2b222231
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartAbstract.java
@@ -0,0 +1,59 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+import com.gitee.qdbp.able.enums.LogicType;
+
+/**
+ * 数据库Where条件容器
+ *
+ * @author zhaohuihua
+ * @version 181221
+ */
+abstract class DbWhereForStartAbstract extends DbWhereBase {
+
+ protected SkipType skipType;
+
+ protected DbWhereForStartAbstract(T root, DbItems where, SkipType skipType) {
+ super(root, where);
+ this.skipType = skipType;
+ }
+
+ protected abstract DbWhereForStartCore getStartWhere();
+
+ /**
+ * AND查询条件
+ *
+ * @param fieldName 字段名称
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForFieldCore and(String fieldName) {
+ return new DbWhereForFieldCore<>(getStartWhere(), skipType, LogicType.AND, fieldName);
+ }
+
+ /**
+ * OR查询条件
+ *
+ * @param fieldName 字段名称
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForFieldCore or(String fieldName) {
+ return new DbWhereForFieldCore<>(getStartWhere(), skipType, LogicType.OR, fieldName);
+ }
+
+ /**
+ * AND查询条件
+ *
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForFieldless and() {
+ return new DbWhereForFieldless<>(getStartWhere(), skipType, LogicType.AND);
+ }
+
+ /**
+ * OR查询条件
+ *
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForFieldless or() {
+ return new DbWhereForFieldless<>(getStartWhere(), skipType, LogicType.OR);
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartByField.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartByField.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f163ae39120b2a842104dad58a09ac7a9389091
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartByField.java
@@ -0,0 +1,41 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+import com.gitee.qdbp.able.enums.LogicType;
+
+/**
+ * 数据库Where条件容器
+ *
+ * @author zhaohuihua
+ * @version 181221
+ */
+public class DbWhereForStartByField extends DbWhereBase {
+
+ protected DbWhereForStartCore start;
+ private SkipType skipType;
+
+ protected DbWhereForStartByField(DbWhereForStartCore start, SkipType skipType) {
+ super(start.root, start.items);
+ this.start = start;
+ this.skipType = skipType;
+ }
+
+ /**
+ * AND查询条件
+ *
+ * @param fieldName 字段名称
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForFieldBase and(String fieldName) {
+ return new DbWhereForFieldBase<>(start, skipType, LogicType.AND, fieldName);
+ }
+
+ /**
+ * OR查询条件
+ *
+ * @param fieldName 字段名称
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForFieldBase or(String fieldName) {
+ return new DbWhereForFieldBase<>(start, skipType, LogicType.OR, fieldName);
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartContinue.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartContinue.java
new file mode 100644
index 0000000000000000000000000000000000000000..527ae05df5971b3110e5ecc6e36fed4c1de787f7
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartContinue.java
@@ -0,0 +1,22 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+/**
+ * 数据库Where条件容器
+ *
+ * @author zhaohuihua
+ * @version 181221
+ */
+public class DbWhereForStartContinue extends DbWhereForStartAbstract {
+
+ protected DbWhereForStartCore start;
+
+ protected DbWhereForStartContinue(DbWhereForStartCore start, SkipType skipType) {
+ super(start.root, start.items, skipType);
+ this.start = start;
+ }
+
+ @Override
+ protected DbWhereForStartCore getStartWhere() {
+ return start;
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartCore.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartCore.java
new file mode 100644
index 0000000000000000000000000000000000000000..577f2840d914f5bbd577a6ca94033f368940163d
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/DbWhereForStartCore.java
@@ -0,0 +1,52 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+/**
+ * 数据库Where条件容器
+ *
+ * @author zhaohuihua
+ * @version 181221
+ */
+public class DbWhereForStartCore extends DbWhereForStartAbstract {
+
+ public DbWhereForStartCore(T root, DbItems items) {
+ super(root, items, SkipType.NONE);
+ }
+
+ @Override
+ protected DbWhereForStartCore getStartWhere() {
+ return this;
+ }
+
+ public T end() {
+ return root;
+ }
+
+ /**
+ * 只有当判断条件为true时才添加查询条件
+ *
+ * @param ifValue 判断条件
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartContinue ifTrue(boolean ifValue) {
+ return new DbWhereForStartContinue(this, ifValue ? SkipType.NONE : SkipType.SKIP);
+ }
+
+ /**
+ * 只有当目标值不为空时才添加查询条件
+ *
+ * @param value 目标值
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartContinue ifHasValue(Object value) {
+ return new DbWhereForStartContinue<>(this, InnerUtils.isBlank(value) ? SkipType.SKIP : SkipType.NONE);
+ }
+
+ /**
+ * 只有当字段值不为空时才添加查询条件
+ *
+ * @return 返回后续流式操作对象
+ */
+ public DbWhereForStartByField ifHasValue() {
+ return new DbWhereForStartByField<>(this, SkipType.BLANK_VALUE);
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/InnerUtils.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/InnerUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..e48a2f6fce20845e5b26a06f599ec256934b2ab4
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/InnerUtils.java
@@ -0,0 +1,21 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+import com.gitee.qdbp.tools.utils.VerifyTools;
+
+class InnerUtils {
+
+ public static boolean isBlank(Object... fieldValues) {
+ if (fieldValues == null) {
+ return true;
+ } else if (fieldValues.length == 0) {
+ return true;
+ } else {
+ for (Object object : fieldValues) {
+ if (VerifyTools.isNotBlank(object)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/LogicField.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/LogicField.java
new file mode 100644
index 0000000000000000000000000000000000000000..6bf05f4400b0b38c50f5d25bf50fcb91e95ea322
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/LogicField.java
@@ -0,0 +1,65 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+import com.gitee.qdbp.able.enums.LogicType;
+import com.gitee.qdbp.able.jdbc.base.LogicCondition;
+import com.gitee.qdbp.tools.utils.VerifyTools;
+
+class LogicField extends DbField implements LogicCondition {
+
+ /** serialVersionUID **/
+ private static final long serialVersionUID = 1L;
+
+ private final LogicType logicType;
+
+ /** 构造函数 **/
+ public LogicField(LogicType logicType) {
+ this.logicType = logicType;
+ }
+
+ /** 构造函数 **/
+ protected LogicField(LogicType logicType, DbField field) {
+ super(field.getOperateType(), field.getFieldName(), field.getFieldValue());
+ this.logicType = logicType;
+ }
+
+ /** 构造函数 **/
+ public LogicField(LogicType logicType, String fieldName, Object fieldValue) {
+ super(fieldName, fieldValue);
+ this.logicType = logicType;
+ }
+
+ /** 构造函数 **/
+ public LogicField(LogicType logicType, String operateType, String fieldName, Object fieldValue) {
+ super(operateType, fieldName, fieldValue);
+ this.logicType = logicType;
+ }
+
+ @Override
+ public LogicType getLogicType() {
+ return logicType;
+ }
+
+ @Override
+ public LogicField copy() {
+ LogicType logicType = this.getLogicType();
+ String operateType = this.getOperateType();
+ String fieldName = this.getFieldName();
+ Object fieldValue = this.getFieldValue();
+ return new LogicField(logicType, operateType, fieldName, fieldValue);
+ }
+
+ public static LogicField of(LogicType logicType, String fieldName, String operate, Object... fieldValues) {
+ VerifyTools.nvl(fieldName, "fieldName");
+ LogicField condition = new LogicField(logicType);
+ condition.setFieldName(fieldName);
+ condition.setOperateType(operate);
+ if (fieldValues != null && fieldValues.length > 0) {
+ if (fieldValues.length == 1) {
+ condition.setFieldValue(fieldValues[0]);
+ } else {
+ condition.setFieldValue(fieldValues);
+ }
+ }
+ return condition;
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/SkipType.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/SkipType.java
new file mode 100644
index 0000000000000000000000000000000000000000..c666ab44b7a84e1b4bdb117b945e0d9f852fda5c
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/SkipType.java
@@ -0,0 +1,11 @@
+package com.gitee.qdbp.able.jdbc.condition;
+
+
+public enum SkipType {
+ /** 不跳过 **/
+ NONE,
+ /** 始终跳过 **/
+ SKIP,
+ /** 字段值为空时跳过 **/
+ BLANK_VALUE
+}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/SubWhere.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/SubWhere.java
index 1d915c99baed84feb9e6b62f87ce28b5f3245c96..fa476407c8389aa97b5133e14c7bc2fa98972e5d 100644
--- a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/SubWhere.java
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/SubWhere.java
@@ -4,7 +4,6 @@ import com.gitee.qdbp.able.enums.LogicType;
import com.gitee.qdbp.able.enums.MatchType;
import com.gitee.qdbp.able.jdbc.base.LogicCondition;
import com.gitee.qdbp.able.jdbc.base.MatchCondition;
-import com.gitee.qdbp.able.jdbc.base.WhereCondition;
/**
* 子查询条件
@@ -17,8 +16,6 @@ public class SubWhere extends DbWhere implements LogicCondition, MatchCondition
/** SerialVersionUID **/
private static final long serialVersionUID = 1L;
- /** 所属上级 **/
- private DbWhere parent;
/** 逻辑联连类型: AND / OR **/
private LogicType logicType;
/** 匹配模式 **/
@@ -27,35 +24,11 @@ public class SubWhere extends DbWhere implements LogicCondition, MatchCondition
protected SubWhere() {
}
- public SubWhere(DbWhere parent, LogicType logicType, MatchType matchType) {
- this.parent = parent;
+ protected SubWhere(LogicType logicType, MatchType matchType) {
this.logicType = logicType;
this.matchType = matchType;
}
- @Override
- public SubWhere on(String fieldName, String operate, Object... fieldValues) {
- super.on(fieldName, operate, fieldValues);
- return this;
- }
-
- /** 增加自定义条件 **/
- @Override
- public SubWhere on(WhereCondition condition) {
- super.put(condition);
- return this;
- }
-
- /** 返回上级 **/
- public DbWhere end() {
- return this.parent;
- }
-
- protected DbWhere setParent(DbWhere parent) {
- this.parent = parent;
- return this;
- }
-
/** 逻辑联连类型: AND / OR **/
@Override
public LogicType getLogicType() {
@@ -88,7 +61,6 @@ public class SubWhere extends DbWhere implements LogicCondition, MatchCondition
protected void copyTo(SubWhere copies) {
super.copyTo(copies);
- copies.parent = this.parent;
copies.logicType = this.logicType;
copies.matchType = this.matchType;
}
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/TableJoin.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/TableJoin.java
index 4d4da140e40ced9e2b400cd3ee99d2b7826f6614..e99daf3edb39f55669eca6eea695c6238081e47b 100644
--- a/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/TableJoin.java
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/condition/TableJoin.java
@@ -3,6 +3,7 @@ package com.gitee.qdbp.able.jdbc.condition;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
+import com.gitee.qdbp.able.enums.LogicType;
import com.gitee.qdbp.tools.utils.NamingTools;
import com.gitee.qdbp.tools.utils.VerifyTools;
@@ -24,20 +25,21 @@ import com.gitee.qdbp.tools.utils.VerifyTools;
*
List<String> userCodes = Arrays.asList("evan", "kelly", "coral");
// @formatter:off
- TableJoin tables = new TableJoin(SysUser.class, "u", "user")
+ TableJoin tables = new TableJoin(SysUser.class, "u").saveTo("user")
.innerJoin(SysUserRole.class, "ur")
- .on("u.id", "=", "ur.userId")
- .and("ur.dataState", "=", 1)
- .innerJoin(SysRole.class, "r", "role")
- .on("ur.roleId", "=", "r.id")
- .and("r.dataState", "=", 1)
+ .on("u.id").equals("ur.userId")
+ .and("ur.dataState").equals(1)
+ .end()
+ .innerJoin(SysRole.class, "r").saveTo("role")
+ .on("ur.roleId").equals("r.id")
+ .and("r.dataState").equals(1)
.end();
// @formatter:on
// UserRole = { SysUser user; SysRole role; }
// 这里不关注SysUserRole
// 因此innerJoin(SysUserRole.class, "ur")未指定第3个参数resultField
// 不会出现在SELECT后面的字段列表中, 也就不会保存查询结果
- JoinQueryer<UserRole> query = qdbcBoot.buildJoinQuery(tables, UserRole.class);
+ JoinQueryer<UserRole> query = qdbcBoot.joinQueryer(tables, UserRole.class);
DbWhere where = new DbWhere();
where.on("u.userCode", "in", userCodes);
PageList<UserRole> userRoles = query.list(where, OrderPaging.NONE);
@@ -57,7 +59,7 @@ import com.gitee.qdbp.tools.utils.VerifyTools;
// @formatter:on
DbWhere where = new DbWhere();
where.on("u.userId", "=", userId);
- JoinQueryer<SysRole> query = qdbcBoot.buildJoinQuery(tables, SysRole.class);
+ JoinQueryer<SysRole> query = qdbcBoot.joinQueryer(tables, SysRole.class);
PageList<SysRole> roles = query.list(where, OrderPaging.NONE);
log.debug("RolesQueryByUser: {}", JsonTools.toLogString(roles));
*
@@ -88,19 +90,18 @@ public class TableJoin implements Serializable {
}
/**
- * 构造函数
+ * 设置数据保存字段名
*
- * @param tableType 主表类型
- * @param tableAlias 主表别名
- * @param resultField 数据保存至结果类的哪个字段(子对象), this表示结果字段放在主对象中
+ * @param resultField 数据保存至结果类的哪个字段(子对象), "this"表示结果字段放在主对象中
+ * @return 返回当前对象
*/
- public TableJoin(Class> tableType, String tableAlias, String resultField) {
- this.major = new TableItem(tableType, tableAlias, resultField);
- this.joins = new ArrayList<>();
+ public TableJoin saveTo(String resultField) {
+ this.major.resultField = resultField;
+ return this;
}
/**
- * 增加 inner join 表连接, 仅用于表关联, 不取返回结果(如果需要返回结果请添加resultField字段)
+ * 增加 inner join 表连接
*
* @param tableType 表类型
* @param tableAlias 表别名
@@ -143,61 +144,13 @@ public class TableJoin implements Serializable {
return joinStart(tableType, tableAlias, JoinType.FullJoin);
}
- /**
- * 增加 inner join 表连接
- *
- * @param tableType 表类型
- * @param tableAlias 表别名
- * @param resultField 数据保存至结果类的哪个字段(子对象), this表示结果字段放在主对象中
- * @return JoinStart 用于添加on条件
- */
- public JoinStart innerJoin(Class> tableType, String tableAlias, String resultField) {
- return joinStart(tableType, tableAlias, resultField, JoinType.InnerJoin);
- }
-
- /**
- * 增加 left join 表连接
- *
- * @param tableType 表类型
- * @param tableAlias 表别名
- * @param resultField 数据保存至结果类的哪个字段(子对象), this表示结果字段放在主对象中
- * @return JoinStart 用于添加on条件
- */
- public JoinStart leftJoin(Class> tableType, String tableAlias, String resultField) {
- return joinStart(tableType, tableAlias, resultField, JoinType.LeftJoin);
- }
-
- /**
- * 增加 right join 表连接
- *
- * @param tableType 表类型
- * @param tableAlias 表别名
- * @param resultField 数据保存至结果类的哪个字段(子对象), this表示结果字段放在主对象中
- * @return JoinStart 用于添加on条件
- */
- public JoinStart rightJoin(Class> tableType, String tableAlias, String resultField) {
- return joinStart(tableType, tableAlias, resultField, JoinType.RightJoin);
- }
-
- /**
- * 增加 full join 表连接
- *
- * @param tableType 表类型
- * @param tableAlias 表别名
- * @param resultField 数据保存至结果类的哪个字段(子对象), this表示结果字段放在主对象中
- * @return JoinStart 用于添加on条件
- */
- public JoinStart fullJoin(Class> tableType, String tableAlias, String resultField) {
- return joinStart(tableType, tableAlias, resultField, JoinType.FullJoin);
- }
-
/** 主表 **/
public TableItem getMajor() {
return major;
}
/** 主表 **/
- public void setMajor(TableItem major) {
+ protected void setMajor(TableItem major) {
this.major = major;
}
@@ -207,7 +160,7 @@ public class TableJoin implements Serializable {
}
/** 关联表 **/
- public void setJoins(List joins) {
+ protected void setJoins(List joins) {
this.joins = joins;
}
@@ -259,7 +212,7 @@ public class TableJoin implements Serializable {
}
/** 表类型 **/
- public void setTableType(Class> tableType) {
+ protected void setTableType(Class> tableType) {
this.tableType = tableType;
}
@@ -269,7 +222,7 @@ public class TableJoin implements Serializable {
}
/** 别名 **/
- public void setTableAlias(String tableAlias) {
+ protected void setTableAlias(String tableAlias) {
this.tabletableAlias = tableAlias;
}
@@ -279,10 +232,9 @@ public class TableJoin implements Serializable {
}
/** 数据保存至结果类的哪个字段(子对象), this表示结果字段放在主对象中 **/
- public void setResultField(String resultField) {
+ protected void setResultField(String resultField) {
this.resultField = resultField;
}
-
}
public static class JoinItem extends TableItem {
@@ -306,6 +258,16 @@ public class TableJoin implements Serializable {
this.joinType = joinType;
this.where = where;
}
+ /**
+ * 设置数据保存字段名
+ *
+ * @param resultField 数据保存至结果类的哪个字段(子对象), "this"表示结果字段放在主对象中
+ * @return 返回当前对象
+ */
+ public JoinItem saveTo(String resultField) {
+ this.setResultField(resultField);
+ return this;
+ }
/** 连接类型 **/
public JoinType getJoinType() {
@@ -313,7 +275,7 @@ public class TableJoin implements Serializable {
}
/** 连接类型 **/
- public void setJoinType(JoinType type) {
+ protected void setJoinType(JoinType type) {
this.joinType = type;
}
@@ -323,7 +285,7 @@ public class TableJoin implements Serializable {
}
/** 连接条件 **/
- public void setWhere(DbWhere where) {
+ protected void setWhere(DbWhere where) {
this.where = where;
}
@@ -339,10 +301,29 @@ public class TableJoin implements Serializable {
this.join = join;
}
+ /**
+ * 设置数据保存字段名
+ *
+ * @param resultField 数据保存至结果类的哪个字段(子对象), "this"表示结果字段放在主对象中
+ * @return 返回当前对象
+ */
+ public JoinStart saveTo(String resultField) {
+ this.join.current.setResultField(resultField);
+ return this;
+ }
+
/** 增加连接条件 **/
- public JoinOn on(String fieldName, String operate, Object... fieldValues) {
- this.join.current.where.on(fieldName, operate, fieldValues);
- return new JoinOn(join);
+ public DbWhereForFieldCore on(String fieldName) {
+ JoinOn next = new JoinOn(join);
+ DbWhereForStartCore start = new DbWhereForStartCore<>(next, this.join.current.where);
+ return new DbWhereForFieldCore<>(start, SkipType.NONE, LogicType.AND, fieldName);
+ }
+
+ /** 增加连接条件 **/
+ public DbWhereForOnFieldless on() {
+ JoinOn next = new JoinOn(join);
+ DbWhereForStartCore start = new DbWhereForStartCore<>(next, this.join.current.where);
+ return new DbWhereForOnFieldless<>(start, SkipType.NONE);
}
public TableJoin end() {
@@ -364,12 +345,6 @@ public class TableJoin implements Serializable {
return this.join;
}
- /** 增加连接条件 **/
- public JoinOn and(String fieldName, String operate, Object... fieldValues) {
- this.join.current.where.on(fieldName, operate, fieldValues);
- return this;
- }
-
/** 增加InnerJoin表连接 **/
public JoinStart innerJoin(Class> tableType, String tableAlias) {
return this.join.joinStart(tableType, tableAlias, JoinType.InnerJoin);
@@ -390,25 +365,6 @@ public class TableJoin implements Serializable {
return this.join.joinStart(tableType, tableAlias, JoinType.FullJoin);
}
- /** 增加InnerJoin表连接 **/
- public JoinStart innerJoin(Class> tableType, String tableAlias, String resultField) {
- return this.join.joinStart(tableType, tableAlias, resultField, JoinType.InnerJoin);
- }
-
- /** 增加LeftJoin表连接 **/
- public JoinStart leftJoin(Class> tableType, String tableAlias, String resultField) {
- return this.join.joinStart(tableType, tableAlias, resultField, JoinType.LeftJoin);
- }
-
- /** 增加RightJoin表连接 **/
- public JoinStart rightJoin(Class> tableType, String tableAlias, String resultField) {
- return this.join.joinStart(tableType, tableAlias, resultField, JoinType.RightJoin);
- }
-
- /** 增加FullJoin表连接 **/
- public JoinStart fullJoin(Class> tableType, String tableAlias, String resultField) {
- return this.join.joinStart(tableType, tableAlias, resultField, JoinType.FullJoin);
- }
}
public static String buildCacheKey(TableJoin tables, boolean simpleName) {
@@ -443,17 +399,17 @@ public class TableJoin implements Serializable {
return buildCacheKey(this, true);
}
- /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.buildSqlBuilder(tables), 不能用于qdbcBoot.buildJoinQuery(tables) **/
+ /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.sqlBuilder(tables), 不能用于qdbcBoot.joinQueryer(tables) **/
public static TableJoin of(Class> clazz1, String alias1) {
return new TableJoin(clazz1, alias1);
}
- /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.buildSqlBuilder(tables), 不能用于qdbcBoot.buildJoinQuery(tables) **/
+ /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.sqlBuilder(tables), 不能用于qdbcBoot.joinQueryer(tables) **/
public static TableJoin of(Class> clazz1, String alias1, Class> clazz2, String alias2) {
return new TableJoin(clazz1, alias1).innerJoin(clazz2, alias2).end();
}
- /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.buildSqlBuilder(tables), 不能用于qdbcBoot.buildJoinQuery(tables) **/
+ /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.sqlBuilder(tables), 不能用于qdbcBoot.joinQueryer(tables) **/
public static TableJoin of(Class> clazz1, String alias1, Class> clazz2, String alias2, Class> clazz3,
String alias3) {
TableJoin tables = new TableJoin(clazz1, alias1);
@@ -462,7 +418,7 @@ public class TableJoin implements Serializable {
return tables;
}
- /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.buildSqlBuilder(tables), 不能用于qdbcBoot.buildJoinQuery(tables) **/
+ /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.sqlBuilder(tables), 不能用于qdbcBoot.joinQueryer(tables) **/
public static TableJoin of(Class> clazz1, String alias1, Class> clazz2, String alias2, Class> clazz3,
String alias3, Class> clazz4, String alias4) {
TableJoin tables = new TableJoin(clazz1, alias1);
@@ -472,7 +428,7 @@ public class TableJoin implements Serializable {
return tables;
}
- /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.buildSqlBuilder(tables), 不能用于qdbcBoot.buildJoinQuery(tables) **/
+ /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.sqlBuilder(tables), 不能用于qdbcBoot.joinQueryer(tables) **/
public static TableJoin of(Class> clazz1, String alias1, Class> clazz2, String alias2, Class> clazz3,
String alias3, Class> clazz4, String alias4, Class> clazz5, String alias5) {
TableJoin tables = new TableJoin(clazz1, alias1);
@@ -483,7 +439,7 @@ public class TableJoin implements Serializable {
return tables;
}
- /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.buildSqlBuilder(tables), 不能用于qdbcBoot.buildJoinQuery(tables) **/
+ /** 构造多表关联关系, 由于缺少on语句, 只能用于qdbcBoot.sqlBuilder(tables), 不能用于qdbcBoot.joinQueryer(tables) **/
public static TableJoin of(Class> clazz1, String alias1, Class> clazz2, String alias2, Class> clazz3,
String alias3, Class> clazz4, String alias4, Class> clazz5, String alias5, Class> clazz6,
String alias6) {
diff --git a/able/src/main/java/com/gitee/qdbp/able/jdbc/ordering/Orderings.java b/able/src/main/java/com/gitee/qdbp/able/jdbc/ordering/Orderings.java
index eb89d0268b011f5b601f5ae6ff0a34dc72534158..2101bd9ace57cc397b8845045cd373042e2ade33 100644
--- a/able/src/main/java/com/gitee/qdbp/able/jdbc/ordering/Orderings.java
+++ b/able/src/main/java/com/gitee/qdbp/able/jdbc/ordering/Orderings.java
@@ -82,20 +82,20 @@ public class Orderings extends ArrayList implements Serializable {
container.add(ordering);
String word = sa.readWord();
if (!sa.isLastReadSuccess()) {
- throw new IllegalArgumentException("OrderBy format error: " + sa.readToEnd(index));
+ throw new IllegalArgumentException("OrderBy format error: " + sa.peekToEnd(index));
}
sa.skipWhitespace();
char nextChar = sa.peekChar();
if (nextChar == '.') { // t.userName
String temp = sa.skipChar().readWord();
if (!sa.isLastReadSuccess()) {
- throw new IllegalArgumentException("OrderBy format error: " + sa.readToEnd(index));
+ throw new IllegalArgumentException("OrderBy format error: " + sa.peekToEnd(index));
}
ordering.setOrderBy(word + '.' + temp);
} else if (nextChar == '(') { // pinyin(userName)
List params = sa.readMethodParams();
if (!sa.isLastReadSuccess()) {
- throw new IllegalArgumentException("OrderBy format error: " + sa.readToEnd(index));
+ throw new IllegalArgumentException("OrderBy format error: " + sa.peekToEnd(index));
}
ordering.setFunctionName(word);
// 查找第1个没有单引号包围且不是数字/Boolean/null的字段
@@ -119,34 +119,34 @@ public class Orderings extends ArrayList implements Serializable {
}
sa.skipWhitespace();
if (!sa.isReadable()) {
- ordering.setOriginal(sa.readFrom(index).trim());
+ ordering.setOriginal(sa.peekFrom(index).trim());
} else {
if (sa.peekChar() == ',') {
- ordering.setOriginal(sa.readFrom(index).trim());
+ ordering.setOriginal(sa.peekFrom(index).trim());
sa.skipChar();
continue;
}
String orderType = sa.readWord();
if (!sa.isLastReadSuccess()) {
// 既不是逗号也不是单词
- throw new IllegalArgumentException("OrderBy format error: " + sa.readToEnd(index));
+ throw new IllegalArgumentException("OrderBy format error: " + sa.peekToEnd(index));
}
if ("ASC".equalsIgnoreCase(orderType)) {
ordering.setOrderType(OrderType.ASC);
} else if ("DESC".equalsIgnoreCase(orderType)) {
ordering.setOrderType(OrderType.DESC);
} else { // 既不是ASC也不是DESC
- throw new IllegalArgumentException("OrderBy format error: " + sa.readFrom(index));
+ throw new IllegalArgumentException("OrderBy format error: " + sa.peekFrom(index));
}
sa.skipWhitespace();
if (!sa.isReadable()) {
- ordering.setOriginal(sa.readFrom(index).trim());
+ ordering.setOriginal(sa.peekFrom(index).trim());
} else {
if (sa.peekChar() == ',') {
- ordering.setOriginal(sa.readFrom(index).trim());
+ ordering.setOriginal(sa.peekFrom(index).trim());
sa.skipChar();
} else {
- throw new IllegalArgumentException("OrderBy format error: " + sa.readToEnd(index));
+ throw new IllegalArgumentException("OrderBy format error: " + sa.peekToEnd(index));
}
}
}
diff --git a/able/src/main/java/com/gitee/qdbp/eachfile/process/BaseFileProcessor.java b/able/src/main/java/com/gitee/qdbp/eachfile/process/BaseFileProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..997937623c569354463ae3f0f4db64f9f9fc6dc2
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/eachfile/process/BaseFileProcessor.java
@@ -0,0 +1,205 @@
+package com.gitee.qdbp.eachfile.process;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+import com.gitee.qdbp.able.debug.Debugger;
+import com.gitee.qdbp.tools.files.PathTools;
+import com.gitee.qdbp.tools.utils.StringTools;
+
+/**
+ * 文件处理接口
+ * 包含与排除不能同时设置(如果同时设置以包含为准)
+ *
+ * @author zhaohuihua
+ * @version 20200218
+ */
+public abstract class BaseFileProcessor implements FileProcessor, Debugger.Aware {
+
+ /** 是否跳过文件夹 **/
+ private boolean skipFolder;
+ /** 是否跳过文件 **/
+ private boolean skipFile;
+ /** 包含的文件夹 **/
+ private Map includeFolders;
+ /** 排除的文件夹 **/
+ private Map excludeFolders;
+ /** 包含的文件名 **/
+ private Map includeFileNames;
+ /** 排除的文件名 **/
+ private Map excludeFileNames;
+ /** 包含的文件类型 **/
+ private Map includeFileTypes;
+ /** 排除的文件类型 **/
+ private Map excludeFileTypes;
+ /** 包含的文件名正则表达式 **/
+ private Pattern includeFilePattern;
+ /** 排除的文件名正则表达式 **/
+ private Pattern excludeFilePattern;
+ /** 日志接口 **/
+ private Debugger debugger;
+
+ public BaseFileProcessor(boolean skipFolder, boolean skipFile) {
+ this.skipFolder = skipFolder;
+ this.skipFile = skipFile;
+ }
+
+ protected void setIncludeFolders(String... includeFolders) {
+ this.includeFolders = toKeyMaps(includeFolders);
+ }
+
+ protected void setExcludeFolders(String... excludeFolders) {
+ this.excludeFolders = toKeyMaps(excludeFolders);
+ }
+
+ protected void setIncludeFileNames(String... includeFileNames) {
+ this.includeFileNames = toKeyMaps(includeFileNames);
+ }
+
+ protected void setExcludeFileNames(String... excludeFileNames) {
+ this.excludeFileNames = toKeyMaps(excludeFileNames);
+ }
+
+ protected void setIncludeFileTypes(String... includeFileTypes) {
+ this.includeFileTypes = toKeyMaps(includeFileTypes);
+ }
+
+ protected void setExcludeFileTypes(String... excludeFileTypes) {
+ this.excludeFileTypes = toKeyMaps(excludeFileTypes);
+ }
+
+ protected void setIncludeFilePattern(String includeFilePattern) {
+ this.includeFilePattern = Pattern.compile(includeFilePattern, Pattern.CASE_INSENSITIVE);
+ }
+
+ protected void setIncludeFilePattern(Pattern includeFilePattern) {
+ this.includeFilePattern = includeFilePattern;
+ }
+
+ protected void setExcludeFilePattern(String excludeFilePattern) {
+ this.excludeFilePattern = Pattern.compile(excludeFilePattern, Pattern.CASE_INSENSITIVE);
+ }
+
+ protected void setExcludeFilePattern(Pattern excludeFilePattern) {
+ this.excludeFilePattern = excludeFilePattern;
+ }
+
+ public static Map toKeyMaps(String... keys) {
+ Map map = new HashMap<>();
+ for (String item : keys) {
+ String[] array = StringTools.split(item, ',');
+ for (String key : array) {
+ map.put(key == null ? null : key.toLowerCase(), null);
+ }
+ }
+ return map;
+ }
+
+ /**
+ * 检查文件
+ *
+ * @param root 根目录
+ * @param file 待处理的文件
+ * @return 是否处理
+ */
+ protected boolean doFileCheck(String root, File file) {
+ return true;
+ }
+
+ /**
+ * 处理文件
+ *
+ * @param root 根目录
+ * @param file 待处理的文件
+ */
+ protected void doFileProcess(String root, File file) {
+ }
+
+ /**
+ * 检查文件夹
+ *
+ * @param root 根目录
+ * @param folder 待处理的文件夹
+ * @return 是否继续, true表示继续处理文件夹中的文件或子文件夹, false表示跳过文件夹
+ */
+ protected boolean doFolderCheck(String root, File folder) {
+ return true;
+ }
+
+ /**
+ * 处理文件夹
+ *
+ * @param root 根目录
+ * @param folder 待处理的文件夹
+ * @return 是否继续, true表示继续处理文件夹中的文件或子文件夹, false表示跳过文件夹
+ */
+ protected boolean doFolderProcess(String root, File folder) {
+ return true;
+ }
+
+ @Override
+ public final void fileProcess(String root, File file) {
+ String fileName = file.getName().toLowerCase();
+ if (includeFileNames != null && !includeFileNames.containsKey(fileName)) {
+ return;
+ } else if (excludeFileNames != null && excludeFileNames.containsKey(fileName)) {
+ return;
+ }
+ String extension = PathTools.getExtension(fileName, false);
+ if (extension != null) {
+ extension = extension.toLowerCase();
+ }
+ if (includeFileTypes != null && !includeFileTypes.containsKey(extension)) {
+ return;
+ } else if (excludeFileTypes != null && excludeFileTypes.containsKey(extension)) {
+ return;
+ }
+ if (includeFilePattern != null && !includeFilePattern.matcher(fileName).find()) {
+ return;
+ } else if (excludeFilePattern != null && excludeFilePattern.matcher(fileName).find()) {
+ return;
+ }
+ if (!doFileCheck(root, file)) {
+ return;
+ }
+ if (skipFile) {
+ return;
+ }
+ doFileProcess(root, file);
+ }
+
+ @Override
+ public final boolean folderProcess(String root, File folder) {
+ String fileName = folder.getName().toLowerCase();
+ if (includeFolders != null && !includeFolders.containsKey(fileName)) {
+ return false;
+ } else if (excludeFolders != null && excludeFolders.containsKey(fileName)) {
+ return false;
+ }
+ if (!doFolderCheck(root, folder)) {
+ return false;
+ }
+ if (skipFolder) {
+ return true;
+ }
+ return doFolderProcess(root, folder);
+ }
+
+ /** 日志接口 **/
+ public Debugger getDebugger() {
+ return debugger;
+ }
+
+ /** 日志接口 **/
+ @Override
+ public void setDebugger(Debugger listener) {
+ this.debugger = listener;
+ }
+
+ protected void debug(String message, Object... args) {
+ if (this.debugger != null) {
+ this.debugger.debug(message, args);
+ }
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/eachfile/process/FileProcessor.java b/able/src/main/java/com/gitee/qdbp/eachfile/process/FileProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..149d47687b9b8dd78be8cfe54a7d8149ea46214d
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/eachfile/process/FileProcessor.java
@@ -0,0 +1,29 @@
+package com.gitee.qdbp.eachfile.process;
+
+import java.io.File;
+
+/**
+ * 文件处理接口
+ *
+ * @author zhaohuihua
+ * @version 20200218
+ */
+public interface FileProcessor {
+
+ /**
+ * 处理文件
+ *
+ * @param root 根目录
+ * @param file 待处理的文件
+ */
+ void fileProcess(String root, File file);
+
+ /**
+ * 处理文件夹
+ *
+ * @param root 根目录
+ * @param folder 待处理的文件夹
+ * @return 是否继续, false表示跳过后面的文件
+ */
+ boolean folderProcess(String root, File folder);
+}
diff --git a/able/src/main/java/com/gitee/qdbp/eachfile/process/FilterFileProcessor.java b/able/src/main/java/com/gitee/qdbp/eachfile/process/FilterFileProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..91c1e84b46f5784c98727babac7706b79d3bf1e3
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/eachfile/process/FilterFileProcessor.java
@@ -0,0 +1,66 @@
+package com.gitee.qdbp.eachfile.process;
+
+import java.util.regex.Pattern;
+
+/**
+ * 可以设置限制条件的处理器
+ *
+ * @author zhaohuihua
+ * @version 20200426
+ */
+public abstract class FilterFileProcessor extends BaseFileProcessor {
+
+ public FilterFileProcessor(boolean skipFolder, boolean skipFile) {
+ super(skipFolder, skipFile);
+ }
+
+ @Override
+ public void setIncludeFolders(String... includeFolders) {
+ super.setIncludeFolders(includeFolders);
+ }
+
+ @Override
+ public void setExcludeFolders(String... excludeFolders) {
+ super.setExcludeFolders(excludeFolders);
+ }
+
+ @Override
+ public void setIncludeFileNames(String... includeFileNames) {
+ super.setIncludeFileNames(includeFileNames);
+ }
+
+ @Override
+ public void setExcludeFileNames(String... excludeFileNames) {
+ super.setExcludeFileNames(excludeFileNames);
+ }
+
+ @Override
+ public void setIncludeFileTypes(String... includeFileTypes) {
+ super.setIncludeFileTypes(includeFileTypes);
+ }
+
+ @Override
+ public void setExcludeFileTypes(String... excludeFileTypes) {
+ super.setExcludeFileTypes(excludeFileTypes);
+ }
+
+ @Override
+ public void setIncludeFilePattern(String includeFilePattern) {
+ super.setIncludeFilePattern(includeFilePattern);
+ }
+
+ @Override
+ public void setIncludeFilePattern(Pattern includeFilePattern) {
+ super.setIncludeFilePattern(includeFilePattern);
+ }
+
+ @Override
+ public void setExcludeFilePattern(String excludeFilePattern) {
+ super.setExcludeFilePattern(excludeFilePattern);
+ }
+
+ @Override
+ public void setExcludeFilePattern(Pattern excludeFilePattern) {
+ super.setExcludeFilePattern(excludeFilePattern);
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/eachfile/runner/FileEachRunner.java b/able/src/main/java/com/gitee/qdbp/eachfile/runner/FileEachRunner.java
new file mode 100644
index 0000000000000000000000000000000000000000..875d282085c1cbca2c994959a4c18bd364f0030e
--- /dev/null
+++ b/able/src/main/java/com/gitee/qdbp/eachfile/runner/FileEachRunner.java
@@ -0,0 +1,156 @@
+package com.gitee.qdbp.eachfile.runner;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.net.URLDecoder;
+import com.gitee.qdbp.able.debug.ConsoleDebugger;
+import com.gitee.qdbp.able.debug.Debugger;
+import com.gitee.qdbp.eachfile.process.FileProcessor;
+import com.gitee.qdbp.tools.files.PathTools;
+import com.gitee.qdbp.tools.utils.StringTools;
+import com.gitee.qdbp.tools.wait.SingleLock;
+
+/**
+ * 文件遍历工具
+ *
+ * @author zhaohuihua
+ * @version 190719
+ */
+public class FileEachRunner extends Thread {
+
+ private final String root;
+ private final FileProcessor processor;
+ private final FileFilter fileFilter;
+ private final Debugger debugger;
+ private SingleLock lock;
+
+ public FileEachRunner(String root, FileProcessor processor) {
+ this(root, null, processor, null);
+ }
+
+ public FileEachRunner(String root, FileProcessor processor, Debugger listener) {
+ this(root, null, processor, listener);
+ }
+
+ public FileEachRunner(String root, FileFilter fileFilter, FileProcessor processor, Debugger debugger) {
+ this.root = PathTools.concat(true, root, "/");
+ this.fileFilter = fileFilter;
+ this.processor = processor;
+ this.debugger = debugger != null ? debugger : new ConsoleDebugger();
+ if (this.processor instanceof Debugger.Aware) {
+ ((Debugger.Aware) this.processor).setDebugger(this.debugger);
+ }
+ }
+
+ @Override
+ public void run() {
+ File folder = new File(root);
+ if (!checkRoot(folder)) {
+ return;
+ }
+
+ each(folder);
+
+ if (lock != null) {
+ lock.signal();
+ }
+ }
+
+ public void await() {
+ if (this.lock == null) {
+ this.lock = new SingleLock();
+ this.lock.await();
+ }
+ }
+
+ protected void each(File folder) {
+ File[] files;
+ if (fileFilter == null) {
+ files = folder.listFiles();
+ } else {
+ files = folder.listFiles(fileFilter);
+ }
+ if (files == null || files.length == 0) {
+ return;
+ }
+ for (File file : files) {
+ if (file.isFile()) {
+ processor.fileProcess(root, file);
+ } else if (file.isDirectory()) {
+ boolean isContinue = processor.folderProcess(root, file);
+ if (isContinue) {
+ each(file);
+ }
+ }
+ }
+ }
+
+ protected boolean checkRoot(File root) {
+ if (root.isFile()) {
+ debugger.debug("根路径必须是文件夹");
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ public String getRoot() {
+ return root;
+ }
+
+ public FileProcessor getProcessor() {
+ return processor;
+ }
+
+ public FileFilter getFileFilter() {
+ return fileFilter;
+ }
+
+ public Debugger getDebugger() {
+ return debugger;
+ }
+
+
+ /**
+ * 获取指定类所在的classpath
+ *
+ * @param clazz 指定类
+ * @return classpath
+ */
+ public static String getClasspath(Class> clazz) {
+ // 获取与JAR包自身所在的文件夹
+ // project-path/target/classes/
+ URL url = clazz.getResource("/");
+ if (url != null) {
+ return PathTools.toUriPath(url);
+ } else { // jar包中获取为空
+ // project-path/target/classes/com/gitee/qdbp/.../
+ // jar:file:/F:/project-path/xxx.jar!/com/gitee/qdbp/.../
+ url = clazz.getResource("");
+ String p = PathTools.toUriPath(url);
+ p = StringTools.removePrefix(p, "jar://");
+ p = StringTools.removePrefix(p, "jar:");
+ p = StringTools.removePrefix(p, "file:");
+ int index = p.indexOf('!');
+ if (index > 0) {
+ p = PathTools.removeFileName(p.substring(0, index));
+ }
+ if ((p.length() > 2) && (p.charAt(2) == ':')) {
+ // "/c:/foo/" --> "c:/foo/"
+ p = p.substring(1);
+ }
+ if (!new File(p).exists() && p.contains("%")) {
+ try {
+ p = URLDecoder.decode(p, "UTF-8");
+ if (!new File(p).exists()) {
+ p = URLDecoder.decode(p, "GBK");
+ }
+ } catch (UnsupportedEncodingException e) {
+ }
+ }
+ return p;
+ }
+ }
+}
diff --git a/able/src/main/java/com/gitee/qdbp/tools/parse/StringAccess.java b/able/src/main/java/com/gitee/qdbp/tools/parse/StringAccess.java
index 737754c78c71b7cf7973899edbba7531efa1d17b..ace4370add93639a08ffdeb122a6c067adefffc9 100644
--- a/able/src/main/java/com/gitee/qdbp/tools/parse/StringAccess.java
+++ b/able/src/main/java/com/gitee/qdbp/tools/parse/StringAccess.java
@@ -4,7 +4,10 @@ import java.util.ArrayList;
import java.util.List;
/**
- * 字符串访问工具类
+ * 字符串访问工具类
+ * 总规则:
+ * -- peekXxx不会移动index; readXxx会移动index
+ * -- 如果已到最后, 将设置lastReadSuccess=true并返回null
*
* @author zhaohuihua
* @version 20210430
@@ -35,7 +38,7 @@ public class StringAccess {
* @param string 源字符串
* @param index 开始位置
* @param multiline 是否支持多行模式: false=最多读取至行尾; true=最多读取至文本结束
- * 如 (1\n2) 在多行模式下正确; 在单行模式下会报错(因为读取到行尾都没找到结束的括号)
+ * 如 读取括号中的内容, (1\n2) 在多行模式下正确; 在单行模式下会报错(因为读取到行尾都没找到结束的括号)
*/
public StringAccess(String string, int index, boolean multiline) {
this.string = string;
@@ -124,13 +127,83 @@ public class StringAccess {
}
public StringAccess skipChars(int size) {
- if (index < length) {
- index += size;
- }
+ this.index = Math.min(index + size, length);
this.lastReadSuccess = true;
return this;
}
+ /**
+ * 读取几个字符
+ * 如果不够读取的数量, 将设置lastReadSuccess=false并返回null
+ *
+ * @param size 期望读取的数量
+ * @return 字符串
+ */
+ public String readChars(int size) {
+ if (index >= length) {
+ this.lastReadSuccess = true;
+ return null;
+ } else if (index + size > length) {
+ this.lastReadSuccess = false;
+ return null;
+ } else {
+ int endIndex = index + size;
+ String substring = string.substring(index, endIndex);
+ this.index = endIndex;
+ this.lastReadSuccess = true;
+ return substring;
+ }
+ }
+
+ /**
+ * 查看几个字符
+ * 如果不够查看的数量, 将返回null
+ *
+ * @param size 期望查看的数量
+ * @return 字符串
+ */
+ public String peekChars(int size) {
+ if (index >= length) {
+ this.lastReadSuccess = true;
+ return null;
+ } else if (index + size > length) {
+ this.lastReadSuccess = false;
+ return null;
+ } else {
+ int endIndex = index + size;
+ this.lastReadSuccess = true;
+ return string.substring(index, endIndex);
+ }
+ }
+
+ /**
+ * 读取连续的指定字符
+ * 如果一个字符都没有读取到, 将设置lastReadSuccess=false并返回null
+ *
+ * @param chars 指定字符
+ * @return 字符串
+ */
+ public String readChars(char... chars) {
+ if (index >= length) {
+ this.lastReadSuccess = true;
+ return null;
+ }
+ int originalIndex = this.index;
+ for (; index < length; index++) {
+ char c = string.charAt(index);
+ if (!isInChars(c, chars)) {
+ break;
+ }
+ }
+ if (this.index == originalIndex) {
+ this.lastReadSuccess = false;
+ return null;
+ } else {
+ this.lastReadSuccess = true;
+ return string.substring(originalIndex, index);
+ }
+ }
+
/** 跳过空白字符 (空格/TAB/换行) **/
public StringAccess skipWhitespace() {
return this.doSkipWhitespace(true);
@@ -141,6 +214,30 @@ public class StringAccess {
return this.doSkipWhitespace(false);
}
+ /** 读取空白字符 (空格/TAB/换行) **/
+ public String readWhitespace() {
+ if (index >= length) {
+ this.lastReadSuccess = true;
+ return null;
+ } else {
+ int originalIndex = this.index;
+ this.doSkipWhitespace(true);
+ return string.substring(originalIndex, index);
+ }
+ }
+
+ /** 读取空格和TAB字符 **/
+ public String readSpaceChars() {
+ if (index >= length) {
+ this.lastReadSuccess = true;
+ return null;
+ } else {
+ int originalIndex = this.index;
+ this.doSkipWhitespace(false);
+ return string.substring(originalIndex, index);
+ }
+ }
+
protected StringAccess doSkipWhitespace(boolean multiline) {
for (; index < length; index++) {
char c = string.charAt(index);
@@ -241,20 +338,155 @@ public class StringAccess {
return originIndex == index ? null : string.substring(originIndex, index);
}
+ /**
+ * 从当前位置开始读取, 直到遇到指定字符
+ * 返回字符串不会包含指定字符
+ * 如果到最后也没遇到指定字符, 将还原位置/设置lastReadSuccess=false/返回null
+ *
+ * @param chars 指定字符
+ * @return 子字符串
+ */
+ public String readUntil(char... chars) {
+ if (index >= length) {
+ this.lastReadSuccess = true;
+ return null;
+ }
+ int newIndex = index;
+ boolean found = false;
+ while (newIndex < length) {
+ char c = string.charAt(newIndex);
+ if (isInChars(c, chars)) {
+ found = true;
+ break;
+ } else if (!multiline && (c == '\r' || c == '\n')) {
+ found = false;
+ break; // 单行模式下遇到换行符, 也是结束
+ } else {
+ newIndex++;
+ continue;
+ }
+ }
+ if (!found) {
+ this.lastReadSuccess = false;
+ return null;
+ } else {
+ this.lastReadSuccess = true;
+ String result = string.substring(index, newIndex);
+ this.index = newIndex;
+ return result;
+ }
+ }
+
+ /**
+ * 从当前位置开始读取, 直到遇到指定字符串
+ * 返回字符串不会包含指定字符串
+ * 如果到最后也没遇到指定字符串, 将还原位置/设置lastReadSuccess=false/返回null
+ *
+ * @param strings 指定字符串
+ * @return 子字符串
+ */
+ public String readUntil(String... strings) {
+ if (index >= length) {
+ this.lastReadSuccess = true;
+ return null;
+ }
+ int newIndex = index;
+ boolean found = false;
+ while (newIndex < length) {
+ if (isStartsWith(string, index, strings)) {
+ found = true;
+ break;
+ }
+ char c = string.charAt(newIndex);
+ if (!multiline && (c == '\r' || c == '\n')) {
+ found = false;
+ break; // 单行模式下遇到换行符, 也是结束
+ } else {
+ newIndex++;
+ continue;
+ }
+ }
+ if (!found) {
+ this.lastReadSuccess = false;
+ return null;
+ } else {
+ this.lastReadSuccess = true;
+ String result = string.substring(index, newIndex);
+ this.index = newIndex;
+ return result;
+ }
+ }
+
+ /**
+ * 从当前位置开始读取, 直到行尾
+ * 返回字符串不会包含指定字符
+ * 如果到最后也没遇到换行符, 将读取到最后
+ *
+ * @return 子字符串
+ */
+ public String readToLineEnd() {
+ if (index >= length) {
+ this.lastReadSuccess = true;
+ return null;
+ }
+ String line = this.readUntil('\n');
+ if (line != null) {
+ return line;
+ } else {
+ return this.readToEnd();
+ }
+ }
+
+ private static boolean isInChars(char c, char... chars) {
+ for (int i = 0; i < chars.length; i++) {
+ if (c == chars[i]) {
+ return true;
+ }
+ }
+ if (c == '\r') {
+ // 如果是\r, 只要chars中包含\n也返回true
+ for (int i = 0; i < chars.length; i++) {
+ if (c == '\n') {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static boolean isStartsWith(String string, int index, String... prefixes) {
+ for (String prefix : prefixes) {
+ if (index + prefix.length() > string.length()) {
+ continue;
+ }
+ if (string.substring(index, index + prefix.length()).equals(prefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/** 从当前位置读取到最后 (如果当前位置已在最后将返回null) **/
public String readToEnd() {
- return doReadToEnd(this.index);
+ String substring = doPeekToEnd(this.index);
+ this.index = this.length;
+ return substring;
}
- /** 从指定位置读取到最后 (如果指定位置已在最后将返回null) **/
- public String readToEnd(int index) {
+ /** 查看从当前位置到最后的字符串 (如果当前位置已在最后将返回null) **/
+ public String peekToEnd() {
+ return doPeekToEnd(this.index);
+ }
+
+ /** 查看从指定位置到最后的字符串 (如果指定位置已在最后将返回null) **/
+ public String peekToEnd(int index) {
if (index < 0 || index > length) {
throw new IndexOutOfBoundsException("Index[" + index + "] out of bounds (0, " + length + ")");
}
- return doReadToEnd(index);
+ return doPeekToEnd(index);
}
- private String doReadToEnd(int index) {
+ private String doPeekToEnd(int index) {
if (index >= length) {
this.lastReadSuccess = true;
return null;
@@ -265,13 +497,13 @@ public class StringAccess {
}
/**
- * 从指定位置读取到当前位置
+ * 查看从指定位置到当前位置的字符串
*
* @param startIndex 开始位置
* @return 子字符串
* @throws IndexOutOfBoundsException 位置超出源字符串范围
*/
- public String readFrom(int startIndex) {
+ public String peekFrom(int startIndex) {
if (startIndex < 0 || startIndex > index) {
throw new IndexOutOfBoundsException("StartIndex[" + startIndex + "] out of bounds (0, " + index + ")");
}
@@ -280,14 +512,14 @@ public class StringAccess {
}
/**
- * 读取子字符串
+ * 查看子字符串
*
* @param startIndex 开始位置
* @param endIndex 结束位置
* @return 子字符串
* @throws IndexOutOfBoundsException 位置超出源字符串范围
*/
- public String readSubstring(int startIndex, int endIndex) {
+ public String peekSubstring(int startIndex, int endIndex) {
if (startIndex < 0 || startIndex > length) {
throw new IndexOutOfBoundsException("StartIndex[" + startIndex + "] out of bounds (0, " + length + ")");
}
@@ -302,6 +534,16 @@ public class StringAccess {
}
}
+ /**
+ * 读取括号中的内容
+ * 返回内容不会包含外层括号
+ * 如果没有找到匹配的括号, 将还原位置/设置lastReadSuccess=false/返回null
+ * 支持括号嵌套, 如 new StringAccess("(1/(a+b))").readInBracket('(', ')')将返回1/(a+b)
+ *
+ * @param leftBracket 左括号
+ * @param rightBracket 右括号
+ * @return 括号中的内容
+ */
public String readInBracket(char leftBracket, char rightBracket) {
if (index >= length) {
this.lastReadSuccess = true;
@@ -329,27 +571,6 @@ public class StringAccess {
return result.substring(1, result.length() - 1).trim(); // pinyin
}
- /**
- * 读取一个单项内容
- *
- * @param stopChar 停止符
- * @param multiline 是否支持多行
- * @return 单项内容
- * @deprecated 改为{@link #readUniterm(char...)}
- */
- @Deprecated
- public String readUniterm(char stopChar, boolean multiline) {
- if (this.multiline == multiline) {
- return readUniterm(stopChar);
- } else {
- boolean originalMultiline = this.multiline;
- this.multiline = multiline;
- String result = readUniterm(stopChar);
- this.multiline = originalMultiline;
- return result;
- }
- }
-
/**
* 读取一个单项内容
* 支持以下这些单项:
@@ -391,27 +612,6 @@ public class StringAccess {
}
}
- /**
- * 读取后续所有的单项内容
- *
- * @param separator 分隔符
- * @param multiline 是否支持多行
- * @return 多个单项内容列表
- * @deprecated 改为{@link #readUniterms(boolean, char...)}
- */
- @Deprecated
- public List readUniterms(char separator, boolean multiline) {
- if (this.multiline == multiline) {
- return readUniterms(separator);
- } else {
- boolean originalMultiline = this.multiline;
- this.multiline = multiline;
- List result = readUniterms(separator);
- this.multiline = originalMultiline;
- return result;
- }
- }
-
/**
* 读取后续所有的单项内容 ( 如果不允许多行将读取至行尾; 如果允许多行将读取至文本结束 )
* 调这个方法应该是期望到行尾或文尾, 都是单项内容
diff --git a/tools/pom.xml b/tools/pom.xml
index 7407fb1501ccc617ff613f518f67bff9100db13a..b42fc0c6d364807717f6b5cfd893a7b450c14ab6 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -10,7 +10,7 @@
qdbp-tools
jar
- 5.2.25
+ 5.3.0
https://gitee.com/qdbp/qdbp-able/
qdbp tools library
diff --git a/tools/src/test/java/com/gitee/qdbp/tools/parse/StringAccessTest.java b/tools/src/test/java/com/gitee/qdbp/tools/parse/StringAccessTest.java
index 21ed867dc4eb47e4f9304234a827345ee04603fd..ab87aebc44c7d939208b9bf7b58406bb12c3ce38 100644
--- a/tools/src/test/java/com/gitee/qdbp/tools/parse/StringAccessTest.java
+++ b/tools/src/test/java/com/gitee/qdbp/tools/parse/StringAccessTest.java
@@ -209,4 +209,28 @@ public class StringAccessTest {
}
Assert.assertEquals(uiterms, null, source);
}
+
+ @Test
+ public void testReadChars15() {
+ StringAccess sa = new StringAccess("ABCDEFG");
+ Assert.assertEquals(sa.readChars(2), "AB");
+ Assert.assertEquals(sa.readChars(3), "CDE");
+ Assert.assertEquals(sa.readChars(2), "FG");
+ Assert.assertEquals(sa.readChars(3), null);
+ }
+
+ @Test
+ public void testReadChars16() {
+ StringAccess sa = new StringAccess("ABCABCDEFG");
+ Assert.assertEquals(sa.readChars('A', 'B', 'C'), "ABCABC");
+ Assert.assertEquals(sa.readChars('A', 'B', 'C'), null);
+ }
+
+ @Test
+ public void testReadInBracket() {
+ StringAccess sa = new StringAccess("calculate(1/(a+b))");
+ Assert.assertEquals(sa.readWord(), "calculate");
+ Assert.assertEquals(sa.readInBracket('(', ')'), "1/(a+b)");
+ }
+
}