|
|
@@ -0,0 +1,638 @@
|
|
|
+package com.poyee.base.mapper.provider.util;
|
|
|
+
|
|
|
+import com.poyee.base.mapper.provider.BaseProvider;
|
|
|
+import com.poyee.base.mapper.provider.domain.LeftJoinInfo;
|
|
|
+import com.poyee.base.mapper.provider.domain.WhereInfo;
|
|
|
+import com.poyee.common.exception.ServiceException;
|
|
|
+import com.poyee.enums.DbMethodEnums;
|
|
|
+import com.poyee.enums.FieldOperator;
|
|
|
+import com.poyee.enums.FieldType;
|
|
|
+import com.poyee.enums.SqlEnums;
|
|
|
+import com.poyee.util.ObjectUtil;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.collections4.CollectionUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.jetbrains.annotations.NotNull;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * SQL 生成工具类
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+public class SqlUtil {
|
|
|
+ // SQL 类型
|
|
|
+ private SqlEnums type = SqlEnums.all;
|
|
|
+ // 父对象
|
|
|
+ private BaseProvider parent;
|
|
|
+
|
|
|
+ public static SqlUtil init(BaseProvider baseProvider){
|
|
|
+ return new SqlUtil( baseProvider);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public SqlUtil buildPage(){
|
|
|
+ this.type = SqlEnums.page;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param baseProvider
|
|
|
+ */
|
|
|
+ private SqlUtil(BaseProvider baseProvider){
|
|
|
+ this.parent = baseProvider;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据已收集的信息生成最终的 SQL 字符串。
|
|
|
+ *
|
|
|
+ * @return 生成的 SQL 字符串
|
|
|
+ */
|
|
|
+ public String toSql() {
|
|
|
+ String sqlString = "";
|
|
|
+ switch (parent.dbMethod){
|
|
|
+ case SELECT_BY_ID:
|
|
|
+ case SELECT:
|
|
|
+ sqlString = buildSelectSql();
|
|
|
+ break;
|
|
|
+ case INSERT:
|
|
|
+ sqlString = buildInsertSql();
|
|
|
+ break;
|
|
|
+ case UPDATE:
|
|
|
+ sqlString = buildUpdateSql();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ log.warn("No select columns or parent is null, returning empty SQL.");
|
|
|
+ throw new ServiceException("No select columns or parent is null.");
|
|
|
+ }
|
|
|
+ return sqlString;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建插入 SQL 语句
|
|
|
+ *
|
|
|
+ * @return 插入 SQL 语句
|
|
|
+ */
|
|
|
+ private String buildInsertSql() {
|
|
|
+ // 非空检查
|
|
|
+ if (parent == null || parent.insertMap == null || parent.insertMap.isEmpty()) {
|
|
|
+ log.warn("Parent or insert map is null or empty, returning empty SQL.");
|
|
|
+ throw new ServiceException("Parent or insert map is null or empty.");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (parent.superTable == null || parent.superTable.getTableName() == null || parent.superTable.getTableName().isEmpty()) {
|
|
|
+ log.warn("Super table or table name is null or empty, returning empty SQL.");
|
|
|
+ throw new ServiceException("Super table or table name is null or empty.");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取键和值列表并进行安全检查
|
|
|
+ List<String> columns = new ArrayList<>(parent.insertMap.keySet());
|
|
|
+ List<Object> values = new ArrayList<>(parent.insertMap.values());
|
|
|
+
|
|
|
+ if (columns.isEmpty() || values.isEmpty()) {
|
|
|
+ log.warn("Insert map contains no valid columns or values, returning empty SQL.");
|
|
|
+ throw new ServiceException("Insert map contains no valid columns or values.");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验列名和值是否合法
|
|
|
+ for (String column : columns) {
|
|
|
+ if (column == null || column.isEmpty()) {
|
|
|
+ log.warn("Invalid column name: {}", column);
|
|
|
+ throw new ServiceException("Invalid column name in insert map.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 构建 SQL 字符串
|
|
|
+ StringBuilder sql = new StringBuilder();
|
|
|
+ sql.append("INSERT INTO ")
|
|
|
+ .append(parent.superTable.getTableName())
|
|
|
+ .append(" (")
|
|
|
+ .append(columns.stream().map(ObjectUtil::escapeIdentifier).collect(Collectors.joining(", "))) // 转义列名
|
|
|
+ .append(") VALUES (")
|
|
|
+ .append(ObjectUtil.join(values)) // 转义值
|
|
|
+ .append(")");
|
|
|
+
|
|
|
+ // 格式化并记录日志
|
|
|
+ String sqlString = sql.toString().trim();
|
|
|
+ log.info("Generated SQL: {}", sqlString); // 记录生成的 SQL
|
|
|
+ return sqlString;
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Error building insert SQL. Parent: {}, Columns: {}, Values: {}", parent, columns, values, e);
|
|
|
+ throw new ServiceException("Error building insert SQL.", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建更新 SQL 语句
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @NotNull
|
|
|
+ private String buildUpdateSql(){
|
|
|
+ // 非空检查
|
|
|
+ if (parent == null || parent.updateMap == null || parent.updateMap.isEmpty()) {
|
|
|
+ log.warn("Parent or update map is null or empty, returning empty SQL.");
|
|
|
+ throw new ServiceException("Parent or update map is null or empty.");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (parent.superTable == null || parent.superTable.getTableName() == null || parent.superTable.getTableName().isEmpty()) {
|
|
|
+ log.warn("Super table or table name is null or empty, returning empty SQL.");
|
|
|
+ throw new ServiceException("Super table or table name is null or empty.");
|
|
|
+ }
|
|
|
+ //取出 id
|
|
|
+ Object value = parent.updateMap.get("id");
|
|
|
+ Object idValue = parent.updateMap.remove("id");
|
|
|
+
|
|
|
+ // 获取键和值列表并进行安全检查
|
|
|
+ List<String> columns = new ArrayList<>(parent.updateMap.keySet());
|
|
|
+ List<Object> values = new ArrayList<>(parent.updateMap.values());
|
|
|
+
|
|
|
+ if (columns.isEmpty() || values.isEmpty()) {
|
|
|
+ log.warn("Update map contains no valid columns or values, returning empty SQL.");
|
|
|
+ throw new ServiceException("Update map contains no valid columns or values.");
|
|
|
+ }
|
|
|
+
|
|
|
+ for (String column : columns) {
|
|
|
+ if (column == null || column.isEmpty()) {
|
|
|
+ log.warn("Invalid column name: {}", column);
|
|
|
+ throw new ServiceException("Invalid column name in update map.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 构建 SQL 字符串
|
|
|
+ StringBuilder sql = new StringBuilder();
|
|
|
+ sql.append("UPDATE ")
|
|
|
+ .append(parent.superTable.getTableName())
|
|
|
+ .append(" SET ");
|
|
|
+ for (int i = 0; i < columns.size(); i++) {
|
|
|
+ sql.append(columns.get(i)).append(" = ");
|
|
|
+ if((values.get(i) instanceof Date)){
|
|
|
+ sql.append("'").append(ObjectUtil.escapeValue(values.get(i))).append("'");
|
|
|
+ }else{
|
|
|
+ sql.append(ObjectUtil.escapeValue(values.get(i))); // 转义值
|
|
|
+ }
|
|
|
+ sql.append(i < columns.size() - 1 ? ", " : " ");
|
|
|
+ }
|
|
|
+ //判断where 是否有值
|
|
|
+ if (!parent.whereInfos.isEmpty()) {
|
|
|
+ appendWhereClauses(sql);
|
|
|
+ } else {
|
|
|
+ sql.append("WHERE ")
|
|
|
+ .append(parent.superTable.getPrimaryKey())
|
|
|
+ .append(" = ")
|
|
|
+ .append(ObjectUtil.escapeValue(value));
|
|
|
+ }
|
|
|
+ //判断是否有条件
|
|
|
+ if(!sql.toString().contains(" WHERE ")){
|
|
|
+ log.warn("No where condition found.");
|
|
|
+ throw new ServiceException("No where condition found.");
|
|
|
+ }
|
|
|
+ return sql.toString();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Error building update SQL. Parent: {}, Columns: {}, Values: {}", parent, columns, values, e);
|
|
|
+ throw new ServiceException("Error building update SQL.", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建 SELECT 语句。
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @NotNull
|
|
|
+ private String buildSelectSql() {
|
|
|
+
|
|
|
+ // 检查是否有选择的列和父对象是否存在,如果不存在,则记录警告并抛出异常
|
|
|
+ if (parent == null || CollectionUtils.isEmpty(parent.selectColumns)) {
|
|
|
+ log.warn("No select columns or parent is null, returning empty SQL.");
|
|
|
+ throw new ServiceException("No select columns or parent is null.");
|
|
|
+ }
|
|
|
+ // 开始构建 SQL 语句的 SELECT 部分
|
|
|
+ StringBuilder sql = new StringBuilder();
|
|
|
+ sql.append("SELECT ")
|
|
|
+ .append(String.join(", ", parent.selectColumns))
|
|
|
+ .append(" ");
|
|
|
+
|
|
|
+ // 依次调用方法以补充 SQL 语句的 FROM、JOIN 和 WHERE 子句
|
|
|
+ appendFromClause(sql);
|
|
|
+ appendJoins(sql);
|
|
|
+ appendWhereClauses(sql);
|
|
|
+
|
|
|
+ // 将构建好的 SQL 字符串进行格式化并记录日志
|
|
|
+ String sqlString = sql.toString().trim();
|
|
|
+ switch (type) {
|
|
|
+ case page:
|
|
|
+ //生成count sql
|
|
|
+ String[] split = sqlString.split("FROM");
|
|
|
+ //获取 表字段 中 distinct
|
|
|
+ String countCount = "0";
|
|
|
+ if(CollectionUtils.isNotEmpty(parent.selectColumns)){
|
|
|
+ List<String> distinctColumns = parent.selectColumns.stream()
|
|
|
+ .filter(column -> column.contains("DISTINCT"))
|
|
|
+ //移除 单字段 as 及之后的字符
|
|
|
+ .map(column -> column.replaceAll("\\s+AS\\s+.*", ""))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if(CollectionUtils.isNotEmpty(distinctColumns)){
|
|
|
+ // 使用逗号分隔
|
|
|
+ countCount = String.join(",", distinctColumns);
|
|
|
+ //末位 为逗号 则删除
|
|
|
+ if(countCount.endsWith(",")){
|
|
|
+ countCount = countCount.substring(0, countCount.length() - 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //生成count sql
|
|
|
+ parent.pageCountSql = "select count("+countCount+") from " + split[1];
|
|
|
+ //拼接排序
|
|
|
+ if (!parent.orderByMap.isEmpty()) {
|
|
|
+ sql.append(" ORDER BY ");
|
|
|
+ List<Integer> list = new ArrayList<>(parent.orderByMap.keySet());
|
|
|
+ Collections.sort(list);
|
|
|
+ for (Integer integer : list) {
|
|
|
+ sql.append(parent.orderByMap.get(integer)).append(",");
|
|
|
+ }
|
|
|
+ sql.deleteCharAt(sql.length() - 1);
|
|
|
+ }
|
|
|
+ //生成分页sql
|
|
|
+ sqlString = sql.append(" LIMIT ")
|
|
|
+ .append(parent.mPage.getSize())
|
|
|
+ .append(" OFFSET ")
|
|
|
+ .append((parent.mPage.getCurrent() - 1) * parent.mPage.getSize())
|
|
|
+ .append(" ")
|
|
|
+ .toString();
|
|
|
+ break;
|
|
|
+ case selectOne:
|
|
|
+ sqlString = sql.append(" LIMIT 1 ").toString();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // 返回构建好的 SQL 字符串
|
|
|
+ //sql 格式化打印
|
|
|
+ log.info("SQL: {}", sqlString);
|
|
|
+ return sqlString;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 拼接 FROM 子句。
|
|
|
+ *
|
|
|
+ * @param sql SQL 字符串构建器
|
|
|
+ */
|
|
|
+ private void appendFromClause(StringBuilder sql) {
|
|
|
+ if (Objects.nonNull(parent.superTable)) {
|
|
|
+ sql.append("FROM ")
|
|
|
+ .append(parent.superTable.getTableName())
|
|
|
+ .append(" ")
|
|
|
+ .append(parent.superTable.getAlias())
|
|
|
+ .append(" ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 将 LEFT JOIN 信息拼接到 SQL 字符串中。
|
|
|
+ *
|
|
|
+ * @param sql SQL 字符串构建器
|
|
|
+ */
|
|
|
+ private void appendJoins(StringBuilder sql) {
|
|
|
+ // 检查是否有左连接信息需要添加
|
|
|
+ if (CollectionUtils.isNotEmpty(parent.leftJoinInfos)) {
|
|
|
+ for (LeftJoinInfo leftJoinInfo : parent.leftJoinInfos) {
|
|
|
+ // 跳过空的 LeftJoinInfo
|
|
|
+ if (leftJoinInfo == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 拼接 LEFT JOIN 子句
|
|
|
+ sql.append("LEFT JOIN ")
|
|
|
+ .append(leftJoinInfo.getTableInfo().getTableName())
|
|
|
+ .append(" ")
|
|
|
+ .append(leftJoinInfo.getTableInfo().getAlias())
|
|
|
+ .append(" ON ")
|
|
|
+ .append(leftJoinInfo.getLeftTableInfo().getAlias())
|
|
|
+ .append(".")
|
|
|
+ .append(leftJoinInfo.getLeftFieldName())
|
|
|
+ .append(" = ")
|
|
|
+ .append(leftJoinInfo.getTableInfo().getAlias())
|
|
|
+ .append(".")
|
|
|
+ .append(leftJoinInfo.getFieldName())
|
|
|
+ .append(" ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将 WHERE 条件拼接到 SQL 字符串中。
|
|
|
+ *
|
|
|
+ * @param sql SQL 字符串构建器
|
|
|
+ */
|
|
|
+ private void appendWhereClauses(StringBuilder sql) {
|
|
|
+ // 检查是否有 WHERE 信息需要添加
|
|
|
+ if (CollectionUtils.isNotEmpty(parent.whereInfos)) {
|
|
|
+ StringBuilder whereSql = new StringBuilder("WHERE ");
|
|
|
+ boolean first = true;
|
|
|
+ // 遍历所有 WHERE 信息并构建 WHERE 子句
|
|
|
+ for (WhereInfo whereInfo : parent.whereInfos) {
|
|
|
+ // 除第一个 WHERE 条件外,其他条件前添加 "AND"
|
|
|
+ if (!first) {
|
|
|
+ whereSql.append("AND ");
|
|
|
+ }
|
|
|
+ // 构建并添加 WHERE 条件
|
|
|
+ String formatSql = buildWhereClause(whereInfo);
|
|
|
+ if(first && StringUtils.isNotBlank(formatSql)){
|
|
|
+ first = false;
|
|
|
+ }
|
|
|
+ whereSql.append(formatSql+" ");
|
|
|
+ }
|
|
|
+ //如果最后语句为 where 则删除
|
|
|
+ if(whereSql.toString().endsWith("AND ")){
|
|
|
+ whereSql.delete(whereSql.length()-4,whereSql.length());
|
|
|
+ }
|
|
|
+ //如果最后语句为 where 则删除
|
|
|
+ if(whereSql.toString().endsWith("WHERE ")){
|
|
|
+ whereSql.delete(whereSql.length()-6,whereSql.length());
|
|
|
+ }
|
|
|
+ // 将构建好的 WHERE 子句添加到 SQL 字符串中
|
|
|
+ sql.append(whereSql);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据WhereInfo对象构建SQL查询的WHERE子句
|
|
|
+ * 此方法用于根据提供的条件信息生成SQL语句中的WHERE部分它检查WhereInfo对象及其属性的有效性,
|
|
|
+ * 然后根据这些属性构建WHERE子句字符串
|
|
|
+ *
|
|
|
+ * @param whereInfo 包含WHERE子句构建所需信息的对象,包括表信息、列名、操作符和值等
|
|
|
+ * @return 返回构建的WHERE子句字符串如果提供的信息不足以构建WHERE子句,则返回空字符串
|
|
|
+ */
|
|
|
+ private String buildWhereClause(WhereInfo whereInfo) {
|
|
|
+ // 检查whereInfo及其关键属性是否存在,如果任一关键属性为空,则返回空字符串
|
|
|
+ if (Objects.isNull(whereInfo) || Objects.isNull(whereInfo.getTableInfo())
|
|
|
+ || (Objects.isNull(whereInfo.getColumn()) && Objects.isNull(whereInfo.getOrColumn())
|
|
|
+ && Objects.isNull(whereInfo.getIsCustom()))
|
|
|
+ || (Objects.nonNull(whereInfo.getIsCustom()) && CollectionUtils.isEmpty(whereInfo.getCustomConditions()))
|
|
|
+ ) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ if(Objects.isNull(whereInfo.getFieldType()) && !FieldOperator.checkEmptyValue(whereInfo.getOperator())
|
|
|
+ && (Objects.isNull(whereInfo.getValue()) || Objects.equals("", whereInfo.getValue()))
|
|
|
+ && (Objects.nonNull(whereInfo.getIsCustom()) && CollectionUtils.isEmpty(whereInfo.getCustomConditions()))){
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ if(Objects.isNull(whereInfo.getFieldType()) && !FieldOperator.checkEmptyValue(whereInfo.getOperator())){
|
|
|
+ whereInfo.setFieldType(FieldType.STRING);
|
|
|
+ }
|
|
|
+ //判断是否是自定义条件 如果是自定义条件 则 拼接自定义条件 并返回
|
|
|
+ if(Objects.nonNull(whereInfo.getIsCustom()) && whereInfo.getIsCustom()) {
|
|
|
+ return buildCustomConditionsWhere(whereInfo);
|
|
|
+ }
|
|
|
+ // 使用StringBuilder来构建WHERE子句
|
|
|
+ StringBuilder clause = new StringBuilder();
|
|
|
+ // 添加表别名和列名到WHERE子句中
|
|
|
+ //如果是更新 则不加别名
|
|
|
+ if(parent.dbMethod == DbMethodEnums.UPDATE){
|
|
|
+ clause.append(whereInfo.getColumn())
|
|
|
+ .append(" ")
|
|
|
+ .append(whereInfo.getOperator().getOperator())
|
|
|
+ .append(" ")
|
|
|
+ ;
|
|
|
+ extractedValue(whereInfo, clause);
|
|
|
+ } else {
|
|
|
+ //判断 column 或 orColumn
|
|
|
+ String alias = whereInfo.getTableInfo().getAlias();
|
|
|
+ if (CollectionUtils.isNotEmpty(whereInfo.getOrColumn())) {
|
|
|
+ clause.append("(");
|
|
|
+ whereInfo.getOrColumn().forEach(column -> {
|
|
|
+ clause.append(alias)
|
|
|
+ .append(".")
|
|
|
+ .append(column)
|
|
|
+ .append(" ")
|
|
|
+ .append(whereInfo.getOperator().getOperator())
|
|
|
+ .append(" ")
|
|
|
+ ;
|
|
|
+ // 添加操作符到WHERE子句中
|
|
|
+ extractedValue(whereInfo, clause);
|
|
|
+ // 判断是否是最后一个列
|
|
|
+ clause.append(whereInfo.getOrColumn().indexOf(column) == whereInfo.getOrColumn().size()-1 ? ")" : " OR ");
|
|
|
+ });
|
|
|
+ }else {
|
|
|
+ clause.append(alias)
|
|
|
+ .append(".")
|
|
|
+ .append(whereInfo.getColumn())
|
|
|
+ .append(" ")
|
|
|
+ // 添加操作符到WHERE子句中
|
|
|
+ .append(whereInfo.getOperator().getOperator())
|
|
|
+ .append(" ");
|
|
|
+ extractedValue(whereInfo, clause);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 返回构建完成的WHERE子句
|
|
|
+ return clause.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果为 true,则 customConditions 中的条件将使用 OR 连接,而不是默认的 AND 连接
|
|
|
+ // 注意:如果 isCustomOr 为 true,则 customConditions 中的条件必须是独立的查询条件,不能依赖于其他条件
|
|
|
+ // 例如:
|
|
|
+ // @Where(table = User.class, isCustomOr = true,
|
|
|
+ // customConditions = {
|
|
|
+ // @CustomCondition(field = "status", operator = FieldOperator.EQ, defaultValue = "active"),
|
|
|
+ // @CustomCondition(field = "role", operator = FieldOperator.IN, orFields = {"admin", "user"})
|
|
|
+ // },{
|
|
|
+ // @CustomCondition(field = "status", operator = FieldOperator.EQ, defaultValue = "logOff")
|
|
|
+ // })
|
|
|
+ // 上述条件将生成 SQL 语句:WHERE (status = 'active' AND role IN ('admin', 'user')) OR (status = 'logOff')
|
|
|
+ // 如果为 false,则 customConditions 中的条件将使用 AND 连接
|
|
|
+ // 例如:
|
|
|
+ // @Where(table = User.class, isCustomOr = false,
|
|
|
+ // customConditions = {
|
|
|
+ // @CustomCondition(field = "status", operator = FieldOperator.EQ, defaultValue = "active"),
|
|
|
+ // @CustomCondition(field = "role", operator = FieldOperator.IN, orFields = {"admin", "user"})
|
|
|
+ // },{
|
|
|
+ // @CustomCondition(field = "status", operator = FieldOperator.EQ, defaultValue = "logOff")
|
|
|
+ // })
|
|
|
+ // 上述条件将生成 SQL 语句:WHERE status = 'active' AND role IN ('admin', 'user') AND status = 'logOff'
|
|
|
+ // 注意:如果 isCustomOr 为 false,则 customConditions 中的条件必须是可以同时成立的条件,否则将导致查询结果为空
|
|
|
+ // 注意:customConditions 中的条件每组条件之间是 AND 关系,而组与组之间 根据 isCustomOr 的值决定是 AND 还是 OR 关系
|
|
|
+ // 默认值为 false,表示使用 AND 连接
|
|
|
+ // 如果需要使用 OR 连接,则需要显式设置 isCustomOr 为 true
|
|
|
+ // 检查参数有效性
|
|
|
+ private String buildCustomConditionsWhere(WhereInfo whereInfo) {
|
|
|
+ if (whereInfo == null || CollectionUtils.isEmpty(whereInfo.getCustomConditions())) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ List<WhereInfo.CustomConditions> customConditions = whereInfo.getCustomConditions();
|
|
|
+ boolean isCustomOr = whereInfo.isCustomOr(); // 获取 isCustomOr 设置
|
|
|
+
|
|
|
+ StringBuilder result = new StringBuilder();
|
|
|
+ String connector = isCustomOr ? " OR " : " AND ";
|
|
|
+ String groupWrapperStart = isCustomOr ? "(" : "";
|
|
|
+ String groupWrapperEnd = isCustomOr ? ")" : "";
|
|
|
+
|
|
|
+ for (int i = 0; i < customConditions.size(); i++) {
|
|
|
+ WhereInfo.CustomConditions conditionsGroup = customConditions.get(i);
|
|
|
+ List<WhereInfo.CustomCondition> conditions = conditionsGroup.getCustomConditionList();
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(conditions)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建当前组的条件
|
|
|
+ StringBuilder groupClause = new StringBuilder();
|
|
|
+ for (int j = 0; j < conditions.size(); j++) {
|
|
|
+ WhereInfo.CustomCondition condition = conditions.get(j);
|
|
|
+ // 构建单个条件
|
|
|
+ String conditionClause = buildSingleCustomCondition(whereInfo, condition);
|
|
|
+
|
|
|
+ if (StringUtils.isNotBlank(conditionClause)) {
|
|
|
+ groupClause.append(conditionClause);
|
|
|
+ if (j < conditions.size() - 1) {
|
|
|
+ groupClause.append(" AND ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (groupClause.length() > 0) {
|
|
|
+ if (i > 0) {
|
|
|
+ result.append(connector);
|
|
|
+ }
|
|
|
+ result.append(groupWrapperStart).append(groupClause).append(groupWrapperEnd);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result.length() > 0 ? "("+ result +")" : "";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建单个自定义条件的 SQL 子句。
|
|
|
+ *
|
|
|
+ * @param whereInfo 用于获取表别名等上下文信息
|
|
|
+ * @param condition 自定义条件对象
|
|
|
+ * @return 单个条件的 SQL 字符串
|
|
|
+ */
|
|
|
+ private String buildSingleCustomCondition(WhereInfo whereInfo, WhereInfo.CustomCondition condition) {
|
|
|
+ if (condition == null || StringUtils.isBlank(condition.getColumn())) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ StringBuilder clause = new StringBuilder();
|
|
|
+ String alias = whereInfo.getTableInfo().getAlias();
|
|
|
+
|
|
|
+ String field = condition.getColumn();
|
|
|
+ String operator = condition.getOperator().getOperator();
|
|
|
+ String defaultValue = condition.getDefaultValue();
|
|
|
+
|
|
|
+ // 获取值列表,用于替换占位符
|
|
|
+ Object value = whereInfo.getValue();
|
|
|
+ String valStr = String.valueOf(value);
|
|
|
+ String[] values = valStr.split(",");
|
|
|
+
|
|
|
+ if (StringUtils.isNotBlank(defaultValue)) {
|
|
|
+ // 使用正则表达式匹配 #{0}, #{1} 等形式的占位符
|
|
|
+ java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("#\\{(\\d+)\\}");
|
|
|
+ java.util.regex.Matcher matcher = pattern.matcher(defaultValue);
|
|
|
+
|
|
|
+ StringBuffer sb = new StringBuffer();
|
|
|
+
|
|
|
+ while (matcher.find()) {
|
|
|
+ String indexStr = matcher.group(1);
|
|
|
+ int index = Integer.parseInt(indexStr);
|
|
|
+
|
|
|
+ // 替换占位符为实际值,若索引越界则保留原值
|
|
|
+ if (index >= 0 && index < values.length) {
|
|
|
+ String replacement = values[index].trim();
|
|
|
+ matcher.appendReplacement(sb, replacement);
|
|
|
+ } else {
|
|
|
+ matcher.appendReplacement(sb, matcher.group(0)); // 保留原占位符
|
|
|
+ }
|
|
|
+ }
|
|
|
+ matcher.appendTail(sb);
|
|
|
+
|
|
|
+ // 使用替换后的值
|
|
|
+ defaultValue = sb.toString();
|
|
|
+ condition.setValue(defaultValue);
|
|
|
+ }else{
|
|
|
+ condition.setValue("");
|
|
|
+ }
|
|
|
+
|
|
|
+ clause.append(alias).append(".").append(field).append(" ").append(operator).append(" ");
|
|
|
+ //拼接值
|
|
|
+ extractedValue(condition,clause);
|
|
|
+
|
|
|
+ return clause.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 提取值
|
|
|
+ * @param whereInfo
|
|
|
+ * @param clause
|
|
|
+ */
|
|
|
+ private static void extractedValue(WhereInfo whereInfo, StringBuilder clause) {
|
|
|
+ //特殊处理 如果是between 或 not between
|
|
|
+ if (whereInfo.getOperator() == FieldOperator.BETWEEN || whereInfo.getOperator() == FieldOperator.NOTBETWEEN) {
|
|
|
+ // 如果是between 或 not between,则添加起始值和结束值到WHERE子句中
|
|
|
+ clause.append(FormatValueUtil.formatStringValue(whereInfo));
|
|
|
+ }else {
|
|
|
+ // 根据字段类型添加相应的值到WHERE子句中
|
|
|
+ if (whereInfo.getFieldType() == FieldType.STRING) {
|
|
|
+ // 对字符串类型进行特殊格式化处理
|
|
|
+ clause.append(FormatValueUtil.formatStringValue(whereInfo));
|
|
|
+ } else if (whereInfo.getFieldType() == FieldType.NUMBER) {
|
|
|
+ // 直接添加数值类型到WHERE子句中,无需额外格式化
|
|
|
+ clause.append(whereInfo.getValue());
|
|
|
+ } else if (whereInfo.getFieldType() == FieldType.DATE) {
|
|
|
+ // 对日期类型进行转义处理,防止SQL注入
|
|
|
+ clause.append("'").append(FormatValueUtil.escapeValue(whereInfo.getValue())).append("'");
|
|
|
+ } else {
|
|
|
+ // 直接添加到WHERE子句中,无需额外格式化
|
|
|
+ clause.append(whereInfo.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 提取值
|
|
|
+ * @param condition
|
|
|
+ * @param clause
|
|
|
+ */
|
|
|
+ private static void extractedValue(WhereInfo.CustomCondition condition, StringBuilder clause) {
|
|
|
+ //特殊处理 如果是between 或 not between
|
|
|
+ if (condition.getOperator() == FieldOperator.BETWEEN || condition.getOperator() == FieldOperator.NOTBETWEEN) {
|
|
|
+ // 如果是between 或 not between,则添加起始值和结束值到WHERE子句中
|
|
|
+ clause.append(FormatValueUtil.formatStringValue(condition));
|
|
|
+ }else {
|
|
|
+ // 根据字段类型添加相应的值到WHERE子句中
|
|
|
+ if (condition.getFieldType() == FieldType.STRING) {
|
|
|
+ // 对字符串类型进行特殊格式化处理
|
|
|
+ clause.append(FormatValueUtil.formatStringValue(condition));
|
|
|
+ } else if (condition.getFieldType() == FieldType.NUMBER) {
|
|
|
+ // 直接添加数值类型到WHERE子句中,无需额外格式化
|
|
|
+ clause.append(condition.getValue());
|
|
|
+ } else if (condition.getFieldType() == FieldType.DATE) {
|
|
|
+ // 对日期类型进行转义处理,防止SQL注入
|
|
|
+ clause.append("'").append(FormatValueUtil.escapeValue(condition.getValue())).append("'");
|
|
|
+ } else {
|
|
|
+ // 直接添加到WHERE子句中,无需额外格式化
|
|
|
+ clause.append(condition.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public SqlUtil buildOne() {
|
|
|
+ this.type = SqlEnums.selectOne;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public SqlUtil buildSum() {
|
|
|
+ this.type = SqlEnums.sum;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|