All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hutool.db.sql.Condition Maven / Gradle / Ivy

Go to download

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

There is a newer version: 5.8.34
Show newest version
package cn.hutool.db.sql;

import cn.hutool.core.clone.CloneSupport;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * 条件对象
* * @author Looly */ public class Condition extends CloneSupport { /** * SQL中 LIKE 语句查询方式
* * @author Looly */ public enum LikeType { /** * 以给定值开头,拼接后的SQL "value%" */ StartWith, /** * 以给定值开头,拼接后的SQL "%value" */ EndWith, /** * 包含给定值,拼接后的SQL "%value%" */ Contains } private static final String OPERATOR_LIKE = "LIKE"; private static final String OPERATOR_IN = "IN"; private static final String OPERATOR_IS = "IS"; private static final String OPERATOR_IS_NOT = "IS NOT"; private static final String OPERATOR_BETWEEN = "BETWEEN"; private static final List OPERATORS = Arrays.asList("<>", "<=", "<", ">=", ">", "=", "!=", OPERATOR_IN); private static final String VALUE_NULL = "NULL"; /** * 字段 */ private String field; /** * 运算符(大于号,小于号,等于号 like 等) */ private String operator; /** * 值 */ private Object value; /** * 是否使用条件值占位符 */ private boolean isPlaceHolder = true; /** * between firstValue and secondValue */ private Object secondValue; /** * 与前一个Condition连接的逻辑运算符,可以是and或or */ private LogicalOperator linkOperator = LogicalOperator.AND; /** * 解析为Condition * * @param field 字段名 * @param expression 表达式或普通值 * @return Condition */ public static Condition parse(String field, Object expression) { return new Condition(field, expression); } // --------------------------------------------------------------- Constructor start /** * 构造 */ public Condition() { } /** * 构造 * * @param isPlaceHolder 是否使用条件值占位符 */ public Condition(boolean isPlaceHolder) { this.isPlaceHolder = isPlaceHolder; } /** * 构造,使用等于表达式(运算符是=) * * @param field 字段 * @param value 值 */ public Condition(String field, Object value) { this(field, "=", value); parseValue(); } /** * 构造 * * @param field 字段 * @param operator 运算符(大于号,小于号,等于号 like 等) * @param value 值 */ public Condition(String field, String operator, Object value) { this.field = field; this.operator = operator; this.value = value; } /** * 构造 * * @param field 字段 * @param value 值 * @param likeType {@link LikeType} */ public Condition(String field, String value, LikeType likeType) { this.field = field; this.operator = OPERATOR_LIKE; this.value = SqlUtil.buildLikeValue(value, likeType, false); } // --------------------------------------------------------------- Constructor end // --------------------------------------------------------------- Getters and Setters start /** * @return 字段 */ public String getField() { return field; } /** * 设置字段名 * * @param field 字段名 */ public void setField(String field) { this.field = field; } /** * 获得运算符
* 大于号,小于号,等于号 等 * * @return 运算符 */ public String getOperator() { return operator; } /** * 设置运算符
* 大于号,小于号,等于号 等 * * @param operator 运算符 */ public void setOperator(String operator) { this.operator = operator; } /** * 获得值 * * @return 值 */ public Object getValue() { return value; } /** * 设置值,不解析表达式 * * @param value 值 */ public void setValue(Object value) { setValue(value, false); } /** * 设置值 * * @param value 值 * @param isParse 是否解析值表达式 */ public void setValue(Object value, boolean isParse) { this.value = value; if (isParse) { parseValue(); } } /** * 是否使用条件占位符 * * @return 是否使用条件占位符 */ public boolean isPlaceHolder() { return isPlaceHolder; } /** * 设置是否使用条件占位符 * * @param isPlaceHolder 是否使用条件占位符 */ public void setPlaceHolder(boolean isPlaceHolder) { this.isPlaceHolder = isPlaceHolder; } /** * 是否 between x and y 类型 * * @return 是否 between x and y 类型 * @since 4.0.1 */ public boolean isOperatorBetween() { return OPERATOR_BETWEEN.equalsIgnoreCase(this.operator); } /** * 是否IN条件 * * @return 是否IN条件 * @since 4.0.1 */ public boolean isOperatorIn() { return OPERATOR_IN.equalsIgnoreCase(this.operator); } /** * 是否IS条件 * * @return 是否IS条件 * @since 4.0.1 */ public boolean isOperatorIs() { return OPERATOR_IS.equalsIgnoreCase(this.operator); } /** * 是否LIKE条件 * * @return 是否LIKE条件 * @since 5.7.14 */ public boolean isOperatorLike() { return OPERATOR_LIKE.equalsIgnoreCase(this.operator); } /** * 检查值是否为null,如果为null转换为 "IS NULL"形式 * * @return this */ public Condition checkValueNull() { if (null == this.value) { this.operator = OPERATOR_IS; this.value = VALUE_NULL; } return this; } /** * 获得between 类型中第二个值 * * @return 值 */ public Object getSecondValue() { return secondValue; } /** * 设置between 类型中第二个值 * * @param secondValue 第二个值 */ public void setSecondValue(Object secondValue) { this.secondValue = secondValue; } /** * 获取与前一个Condition连接的逻辑运算符,可以是and或or * * @return 与前一个Condition连接的逻辑运算符,可以是and或or * @since 5.4.3 */ public LogicalOperator getLinkOperator() { return linkOperator; } /** * 设置与前一个Condition连接的逻辑运算符,可以是and或or * * @param linkOperator 与前一个Condition连接的逻辑运算符,可以是and或or * @since 5.4.3 */ public void setLinkOperator(LogicalOperator linkOperator) { this.linkOperator = linkOperator; } // --------------------------------------------------------------- Getters and Setters end @Override public String toString() { return toString(null); } /** * 转换为条件字符串,并回填占位符对应的参数值 * * @param paramValues 参数列表,用于回填占位符对应参数值 * @return 条件字符串 */ public String toString(List paramValues) { final StringBuilder conditionStrBuilder = StrUtil.builder(); // 判空值 checkValueNull(); // 固定前置,例如:"name ="、"name IN"、"name BETWEEN"、"name LIKE" conditionStrBuilder.append(this.field).append(StrUtil.SPACE).append(this.operator); if (isOperatorBetween()) { buildValuePartForBETWEEN(conditionStrBuilder, paramValues); } else if (isOperatorIn()) { // 类似:" (?,?,?)" 或者 " (1,2,3,4)" buildValuePartForIN(conditionStrBuilder, paramValues); } else { if (isPlaceHolder() && false == isOperatorIs()) { // 使用条件表达式占位符,条件表达式并不适用于 IS NULL conditionStrBuilder.append(" ?"); if (null != paramValues) { paramValues.add(this.value); } } else { // 直接使用条件值 final String valueStr = String.valueOf(this.value); conditionStrBuilder.append(" ").append(isOperatorLike() ? StrUtil.wrap(valueStr, "'") : valueStr); } } return conditionStrBuilder.toString(); } // ----------------------------------------------------------------------------------------------- Private method start /** * 构建BETWEEN语句中的值部分
* 开头必须加空格,类似:" ? AND ?" 或者 " 1 AND 2" * * @param conditionStrBuilder 条件语句构建器 * @param paramValues 参数集合,用于参数占位符对应参数回填 */ private void buildValuePartForBETWEEN(StringBuilder conditionStrBuilder, List paramValues) { // BETWEEN x AND y 的情况,两个参数 if (isPlaceHolder()) { // 使用条件表达式占位符 conditionStrBuilder.append(" ?"); if (null != paramValues) { paramValues.add(this.value); } } else { // 直接使用条件值 conditionStrBuilder.append(CharUtil.SPACE).append(this.value); } // 处理 AND y conditionStrBuilder.append(StrUtil.SPACE).append(LogicalOperator.AND); if (isPlaceHolder()) { // 使用条件表达式占位符 conditionStrBuilder.append(" ?"); if (null != paramValues) { paramValues.add(this.secondValue); } } else { // 直接使用条件值 conditionStrBuilder.append(CharUtil.SPACE).append(this.secondValue); } } /** * 构建IN语句中的值部分
* 开头必须加空格,类似:" (?,?,?)" 或者 " (1,2,3,4)" * * @param conditionStrBuilder 条件语句构建器 * @param paramValues 参数集合,用于参数占位符对应参数回填 */ private void buildValuePartForIN(StringBuilder conditionStrBuilder, List paramValues) { conditionStrBuilder.append(" ("); final Object value = this.value; if (isPlaceHolder()) { Collection valuesForIn; // 占位符对应值列表 if (value instanceof Collection) { // pr#2046@Github valuesForIn = (Collection) value; } else if (value instanceof CharSequence) { valuesForIn = StrUtil.split((CharSequence) value, ','); } else { valuesForIn = Arrays.asList(Convert.convert(Object[].class, value)); } conditionStrBuilder.append(StrUtil.repeatAndJoin("?", valuesForIn.size(), ",")); if (null != paramValues) { paramValues.addAll(valuesForIn); } } else { conditionStrBuilder.append(StrUtil.join(",", value)); } conditionStrBuilder.append(')'); } /** * 解析值表达式
* 支持"<>", "<=", "< ", ">=", "> ", "= ", "!=", "IN", "LIKE", "IS", "IS NOT"表达式
* 如果无法识别表达式,则表达式为"=",表达式与值用空格隔开
* 例如字段为name,那value可以为:"> 1"或者 "LIKE %Tom"此类 */ private void parseValue() { // 当值无时,视为空判定 if (null == this.value) { this.operator = OPERATOR_IS; this.value = VALUE_NULL; return; } // 对数组和集合值按照 IN 处理 if (this.value instanceof Collection || ArrayUtil.isArray(this.value)) { this.operator = OPERATOR_IN; return; } // 其他类型值,跳过 if (false == (this.value instanceof String)) { return; } String valueStr = ((String) value); if (StrUtil.isBlank(valueStr)) { // 空字段不做处理 return; } valueStr = StrUtil.trim(valueStr); // 处理null if (StrUtil.endWithIgnoreCase(valueStr, "null")) { if (StrUtil.equalsIgnoreCase("= null", valueStr) || StrUtil.equalsIgnoreCase("is null", valueStr)) { // 处理"= null"和"is null"转换为"IS NULL" this.operator = OPERATOR_IS; this.value = VALUE_NULL; this.isPlaceHolder = false; return; } else if (StrUtil.equalsIgnoreCase("!= null", valueStr) || StrUtil.equalsIgnoreCase("is not null", valueStr)) { // 处理"!= null"和"is not null"转换为"IS NOT NULL" this.operator = OPERATOR_IS_NOT; this.value = VALUE_NULL; this.isPlaceHolder = false; return; } } final List strs = StrUtil.split(valueStr, StrUtil.C_SPACE, 2); if (strs.size() < 2) { return; } // 处理常用符号和IN final String firstPart = strs.get(0).trim().toUpperCase(); if (OPERATORS.contains(firstPart)) { this.operator = firstPart; // 比较符号后跟大部分为数字,此处做转换(IN不做转换) final String valuePart = strs.get(1); this.value = isOperatorIn() ? valuePart : tryToNumber(valuePart); return; } // 处理LIKE if (OPERATOR_LIKE.equals(firstPart)) { this.operator = OPERATOR_LIKE; this.value = unwrapQuote(strs.get(1)); return; } // 处理BETWEEN x AND y if (OPERATOR_BETWEEN.equals(firstPart)) { final List betweenValueStrs = StrSplitter.splitTrimIgnoreCase(strs.get(1), LogicalOperator.AND.toString(), 2, true); if (betweenValueStrs.size() < 2) { // 必须满足a AND b格式,不满足被当作普通值 return; } this.operator = OPERATOR_BETWEEN; this.value = unwrapQuote(betweenValueStrs.get(0)); this.secondValue = unwrapQuote(betweenValueStrs.get(1)); } } /** * 去掉包围在字符串两端的单引号或双引号 * * @param value 值 * @return 去掉引号后的值 */ private static String unwrapQuote(String value) { if (null == value) { return null; } value = value.trim(); int from = 0; int to = value.length(); char startChar = value.charAt(0); char endChar = value.charAt(value.length() - 1); if (startChar == endChar) { if ('\'' == startChar || '"' == startChar) { from = 1; to--; } } if (from == 0) { // 并不包含,返回原值 return value; } return value.substring(from, to); } /** * 尝试转换为数字,转换失败返回字符串 * * @param value 被转换的字符串值 * @return 转换后的值 */ private static Object tryToNumber(String value) { value = StrUtil.trim(value); if (false == NumberUtil.isNumber(value)) { return value; } try { return NumberUtil.parseNumber(value); } catch (Exception ignore) { return value; } } // ----------------------------------------------------------------------------------------------- Private method end }