diff --git a/pom.xml b/pom.xml index 21f604d..9869dac 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ com.imyeyu.spring timi-spring - 0.0.19 + 0.0.20 jar @@ -141,7 +141,7 @@ com.imyeyu.io timi-io - 0.0.5 + 0.0.6 com.imyeyu.java diff --git a/src/main/java/com/imyeyu/spring/util/BaseSQLProvider.java b/src/main/java/com/imyeyu/spring/util/BaseSQLProvider.java index fa6597d..af83fb4 100644 --- a/src/main/java/com/imyeyu/spring/util/BaseSQLProvider.java +++ b/src/main/java/com/imyeyu/spring/util/BaseSQLProvider.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -81,6 +82,21 @@ public abstract class BaseSQLProvider { * @return SQL */ protected String buildSelectByPageSQL(EntityMeta meta, String tableName, Page page, String offset, String limit) { + return buildSelectByPageSQL(meta, tableName, page, offset, limit, ""); + } + + /** + * 构建分页查询 SQL + * + * @param meta 实体元数据 + * @param tableName 表名 + * @param page 分页参数 + * @param offset 偏移量占位符 + * @param limit 限制数量占位符 + * @param pageParameterPath Page 参数路径前缀 + * @return SQL + */ + protected String buildSelectByPageSQL(EntityMeta meta, String tableName, Page page, String offset, String limit, String pageParameterPath) { StringBuilder sql = new StringBuilder(); sql.append("SELECT %s FROM `%s` WHERE 1 = 1".formatted(meta.selectPageClause, tableName)); @@ -88,7 +104,11 @@ public abstract class BaseSQLProvider { appendSoftDeleteCondition(sql, meta); // 添加 Page 查询条件 - appendPageConditions(sql, page); + if (pageParameterPath.isEmpty()) { + appendPageConditions(sql, page); + } else { + appendPageConditions(sql, page, pageParameterPath); + } // 添加排序 appendOrderBy(sql, meta, page); @@ -107,6 +127,19 @@ public abstract class BaseSQLProvider { * @return SQL */ protected String buildCountByPageSQL(EntityMeta meta, String tableName, Page page) { + return buildCountByPageSQL(meta, tableName, page, ""); + } + + /** + * 构建分页统计 SQL + * + * @param meta 实体元数据 + * @param tableName 表名 + * @param page 分页参数 + * @param pageParameterPath Page 参数路径前缀 + * @return SQL + */ + protected String buildCountByPageSQL(EntityMeta meta, String tableName, Page page, String pageParameterPath) { StringBuilder sql = new StringBuilder(); sql.append("SELECT COUNT(*) FROM `%s` WHERE 1 = 1".formatted(tableName)); @@ -114,7 +147,11 @@ public abstract class BaseSQLProvider { appendSoftDeleteCondition(sql, meta); // 添加 Page 查询条件 - appendPageConditions(sql, page); + if (pageParameterPath.isEmpty()) { + appendPageConditions(sql, page); + } else { + appendPageConditions(sql, page, pageParameterPath); + } return sql.toString(); } @@ -138,30 +175,82 @@ public abstract class BaseSQLProvider { * @param page 分页参数 */ protected void appendPageConditions(StringBuilder sql, Page page) { + appendPageConditions(sql, page, ""); + } + + /** + * 添加 Page 查询条件 + * + * @param sql SQL 构建器 + * @param page 分页参数 + * @param pageParameterPath Page 参数路径前缀 + */ + protected void appendPageConditions(StringBuilder sql, Page page, String pageParameterPath) { // 精准查询 - if (TimiJava.isNotEmpty(page.getEqualsExample())) { - Object obj = page.getEqualsExample(); - EntityMeta metaExample = getEntityMeta(obj.getClass()); - String conditionClause = metaExample.fieldColumnList.stream() - .filter(fc -> fc.isNotEmpty(obj)) - .map(fc -> "`%s` = '%s'".formatted(fc.columnName, fc.getAsString(obj))) - .collect(Collectors.joining(" %s ".formatted(page.getEqualsLogic()))); - if (TimiJava.isNotEmpty(conditionClause)) { - sql.append(" AND ").append(conditionClause); - } - } + appendPageExampleConditions( + sql, + page.getEqualsExample(), + page.getEqualsLogic(), + false, + pageParameterPath + ); + // 模糊查询 - if (TimiJava.isNotEmpty(page.getLikesExample())) { - Object obj = page.getLikesExample(); - EntityMeta metaExample = getEntityMeta(obj.getClass()); - String conditionClause = metaExample.fieldColumnList.stream() - .filter(fc -> fc.isNotEmpty(obj)) - .map(fc -> "`%s` LIKE CONCAT('%%', '%s', '%%')".formatted(fc.columnName, fc.getAsString(obj))) - .collect(Collectors.joining(" %s ".formatted(page.getLikesLogic()))); - if (TimiJava.isNotEmpty(conditionClause)) { - sql.append(" AND (").append(conditionClause).append(')'); - } + appendPageExampleConditions( + sql, + page.getLikesExample(), + page.getLikesLogic(), + true, + pageParameterPath + ); + } + + /** + * 添加一组 Page 示例条件 + * + * @param sql SQL 构建器 + * @param example 示例对象 + * @param logic 条件连接逻辑 + * @param likes 是否使用模糊匹配 + * @param pageParameterPath Page 参数路径前缀 + */ + private void appendPageExampleConditions(StringBuilder sql, Object example, Logic logic, boolean likes, String pageParameterPath) { + if (TimiJava.isEmpty(example)) { + return; } + EntityMeta metaExample = getEntityMeta(example.getClass()); + String parameterPrefix = "%s%s.".formatted(pageParameterPath, likes ? "likesExample" : "equalsExample"); + String conditionClause = metaExample.fieldColumnList.stream() + .map(fc -> buildPageCondition(fc, example, likes, parameterPrefix)) + .filter(Objects::nonNull) + .collect(Collectors.joining(" %s ".formatted(logic == null ? Logic.AND : logic))); + if (TimiJava.isNotEmpty(conditionClause)) { + sql.append(" AND (").append(conditionClause).append(')'); + } + } + + /** + * 构建单个 Page 示例条件 + * + * @param fieldColumn 字段元数据 + * @param example 示例对象 + * @param likes 是否使用模糊匹配 + * @param parameterPrefix 参数路径前缀 + * @return 条件子句;字段值为空时返回 null + */ + private String buildPageCondition(FieldColumn fieldColumn, Object example, boolean likes, String parameterPrefix) { + Object value = fieldColumn.getValue(example); + if (TimiJava.isEmpty(value)) { + return null; + } + if (value instanceof Boolean booleanValue) { + return "`%s` IS %s".formatted(fieldColumn.columnName, booleanValue ? "TRUE" : "FALSE"); + } + String parameter = "#{%s%s}".formatted(parameterPrefix, fieldColumn.fieldName); + if (likes) { + return "`%s` LIKE CONCAT('%%', %s, '%%')".formatted(fieldColumn.columnName, parameter); + } + return "`%s` = %s".formatted(fieldColumn.columnName, parameter); } /** @@ -648,11 +737,7 @@ public abstract class BaseSQLProvider { * @return true 为 null */ public boolean isNull(Object entity) { - try { - return Ref.getFieldValue(entity, field, Object.class) == null; - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } + return getValue(entity) == null; } /** @@ -672,11 +757,7 @@ public abstract class BaseSQLProvider { * @return true 为空 */ public boolean isEmpty(Object entity) { - try { - return TimiJava.isEmpty(Ref.getFieldValue(entity, field, Object.class)); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } + return TimiJava.isEmpty(getValue(entity)); } /** @@ -696,8 +777,18 @@ public abstract class BaseSQLProvider { * @return 字符串值 */ public String getAsString(Object obj) { + return getValue(obj).toString(); + } + + /** + * 获取字段值 + * + * @param entity 实体 + * @return 字段值 + */ + public Object getValue(Object entity) { try { - return field.get(obj).toString(); + return Ref.getFieldValue(entity, field, Object.class); } catch (IllegalAccessException e) { throw new RuntimeException(e); } diff --git a/src/main/java/com/imyeyu/spring/util/DynamicTableSQLProvider.java b/src/main/java/com/imyeyu/spring/util/DynamicTableSQLProvider.java index 6a9c8e1..d8d3143 100644 --- a/src/main/java/com/imyeyu/spring/util/DynamicTableSQLProvider.java +++ b/src/main/java/com/imyeyu/spring/util/DynamicTableSQLProvider.java @@ -25,7 +25,7 @@ public class DynamicTableSQLProvider extends BaseSQLProvider { */ public String selectByPage(ProviderContext context, @Param("tableName") String tableName, @Param("page") Page page) { EntityMeta meta = getEntityMeta(context); - return buildSelectByPageSQL(meta, tableName, page, "#{page.offset}", "#{page.limit}"); + return buildSelectByPageSQL(meta, tableName, page, "#{page.offset}", "#{page.limit}", "page."); } /** @@ -38,7 +38,7 @@ public class DynamicTableSQLProvider extends BaseSQLProvider { */ public String countByPage(ProviderContext context, @Param("tableName") String tableName, @Param("page") Page page) { EntityMeta meta = getEntityMeta(context); - return buildCountByPageSQL(meta, tableName, page); + return buildCountByPageSQL(meta, tableName, page, "page."); } /** diff --git a/src/main/java/com/imyeyu/spring/util/SQLProvider.java b/src/main/java/com/imyeyu/spring/util/SQLProvider.java index 8ad4fa9..f9cc569 100644 --- a/src/main/java/com/imyeyu/spring/util/SQLProvider.java +++ b/src/main/java/com/imyeyu/spring/util/SQLProvider.java @@ -30,7 +30,7 @@ public class SQLProvider extends BaseSQLProvider { */ public String selectByPage(ProviderContext context, @Param("page") Page page) { EntityMeta meta = getEntityMeta(context); - return buildSelectByPageSQL(meta, meta.table, page, "#{offset}", "#{limit}"); + return buildSelectByPageSQL(meta, meta.table, page, "#{offset}", "#{limit}", ""); } /** @@ -42,7 +42,7 @@ public class SQLProvider extends BaseSQLProvider { */ public String countByPage(ProviderContext context, @Param("page") Page page) { EntityMeta meta = getEntityMeta(context); - return buildCountByPageSQL(meta, meta.table, page); + return buildCountByPageSQL(meta, meta.table, page, ""); } /**