Skip to content

Commit

Permalink
chore-ISelectAbility-加入支持复杂条件拼接的post查询
Browse files Browse the repository at this point in the history
  • Loading branch information
aruis committed Sep 4, 2024
1 parent 2d25977 commit 977740b
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package net.ximatai.muyun.ability.curd.std;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import net.ximatai.muyun.model.PageResult;
import net.ximatai.muyun.model.QueryItem;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public interface IQueryAbility extends ISelectAbility {

List<QueryItem> queryItemList();

@GET
@Path("/queryFields")
default List<QueryItem> queryFields() {
return queryItemList().stream().filter(item -> !item.isHide()).collect(Collectors.toList());
}

@POST
@Path("/view")
default PageResult view(@QueryParam("page") int page,
@QueryParam("limit") int limit,
@QueryParam("orderField") String orderField,
@QueryParam("orderType") String orderType,
Map<String, Object> queryBody) {
return ISelectAbility.super.view(page, limit, orderField, orderType, queryBody, queryItemList());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
import jakarta.ws.rs.QueryParam;
import net.ximatai.muyun.ability.IDatabaseAbility;
import net.ximatai.muyun.ability.IMetadataAbility;
import net.ximatai.muyun.core.exception.QueryException;
import net.ximatai.muyun.core.tool.DateTool;
import net.ximatai.muyun.database.metadata.DBTable;
import net.ximatai.muyun.domain.OrderColumn;
import net.ximatai.muyun.domain.PageResult;
import net.ximatai.muyun.model.OrderColumn;
import net.ximatai.muyun.model.PageResult;
import net.ximatai.muyun.model.QueryItem;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public interface ISelectAbility extends IDatabaseAbility, IMetadataAbility {
Expand All @@ -34,19 +39,111 @@ default List<OrderColumn> getOrderColumns() {
@GET
@Path("/view")
default PageResult view(@QueryParam("page") int page, @QueryParam("limit") int limit, @QueryParam("orderField") String orderField, @QueryParam("orderType") String orderType) {
return view(page, limit, orderField, orderType, null, null);
}

default PageResult view(int page,
int limit,
String orderField,
String orderType,
Map<String, Object> queryBody,
List<QueryItem> queryItemList
) {
DBTable dbTable = getDatabase().getDBInfo().getSchema(getSchemaName()).getTables().get(getMainTable());
List<Object> params = new ArrayList<>();

List<OrderColumn> orderColumns = (orderField != null) ? List.of(new OrderColumn(orderField, orderType)) : getOrderColumns();

String authCondition = "and 1=1";
String baseSql = "select * from (%s) %s where 1=1 %s".formatted(getSelectSql(), getMainTable(), authCondition);
StringBuilder queryCondition = new StringBuilder();

// 查询条件处理
if (queryBody != null && queryItemList != null && !queryItemList.isEmpty()) {
queryBody.forEach((k, v) -> {
StringBuilder condition = new StringBuilder();
QueryItem qi = queryItemList.stream().filter(item -> item.getField().equals(k)).findFirst().orElse(null);

if (qi == null) {
throw new QueryException("查询条件%s未配置,查询失败".formatted(k));
}

condition.append(" and %s ".formatted(qi.getField()));

if (v == null) {
condition.append(" isnull ");
queryCondition.append(condition);
return;
}

QueryItem.SymbolType symbolType = qi.getSymbolType();

if (qi.isDate() || qi.isDatetime()) { // 是日期,需要提前转换
Function<String, Date> converter = s -> qi.isDate() ? DateTool.stringToSqlDate(s) : DateTool.stringToSqlTime(s);

if (v instanceof String s) {
v = converter.apply(s);
} else if (v instanceof List<?> list) {
v = list.stream().map(o -> o instanceof String s ? converter.apply(s) : o).toList();
}
}

switch (symbolType) {
case LIKE:
condition.append(" like ? ");
params.add("%" + v + "%");
break;
case IN, NOT_IN:
if (!(v instanceof List list)) {
throw new QueryException("IN 条件的值必须是列表");
}

if (list.isEmpty()) {
list.add("muyuntage_20240903_nanjing");
}

String symbol = qi.getSymbolType().equals(QueryItem.SymbolType.IN) ? "in" : "not in";
condition.append(" %s (%s) ".formatted(symbol, list.stream().map(x -> "?").collect(Collectors.joining(","))));
params.addAll(list);
break;
case EQUAL, NOT_EQUAL:
String notMark = symbolType.equals(QueryItem.SymbolType.NOT_EQUAL) ? "!" : "";
condition.append(" %s= ? ".formatted(notMark));
params.add(v);
break;
case RANGE:
if (!(v instanceof List list) || list.size() != 2) {
throw new QueryException("区间查询%s的内容必须是长度为2的数组".formatted(k));
}

Object a = list.get(0);
Object b = list.get(1);

if (a != null) {
condition.append(" >= ? ");
params.add(a);
}

if (b != null) {
condition.append(" and %s ".formatted(qi.getField()));
condition.append(" <= ? ");
params.add(b);
}
break;
default:
throw new QueryException("不支持的符号类型: " + symbolType);
}

queryCondition.append(condition);
});
}

String baseSql = "select * from (%s) %s where 1=1 %s %s ".formatted(getSelectSql(), getMainTable(), authCondition, queryCondition);

// 计算总数
long total = (long) getDatabase().row("select count(*) as num from (%s) %s where 1=1 %s ".formatted(getSelectSql(), getMainTable(), authCondition)).get("num");
long total = (long) getDatabase().row("select count(*) as num from (%s) %s where 1=1 %s %s ".formatted(getSelectSql(), getMainTable(), authCondition, queryCondition)).get("num");

// 构建查询 SQL
StringBuilder querySql = new StringBuilder(baseSql);
List<Object> params = new ArrayList<>();

// 添加排序列
if (!orderColumns.isEmpty()) {
Expand All @@ -67,4 +164,5 @@ default PageResult view(@QueryParam("page") int page, @QueryParam("limit") int l

return new PageResult<>(list, total, limit, page);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package net.ximatai.muyun.core.exception;

public class QueryException extends RuntimeException {

public QueryException(String message) {
super(message);
}
}
33 changes: 33 additions & 0 deletions my-core/src/main/java/net/ximatai/muyun/core/tool/DateTool.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package net.ximatai.muyun.core.tool;

import java.sql.Date;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class DateTool {

private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

public static Date stringToSqlDate(String dateString) {
if (dateString == null || dateString.isEmpty()) {
throw new IllegalArgumentException("Date string cannot be null or empty.");
}
dateString = dateString.substring(0, 10);
LocalDate localDate = LocalDate.parse(dateString, DATE_FORMATTER);
return Date.valueOf(localDate);
}

public static Date stringToSqlTime(String dateString) {
if (dateString == null || dateString.isEmpty()) {
throw new IllegalArgumentException("Date string cannot be null or empty.");
}
if (dateString.length() == 10) {
dateString += " 00:00:00";
}
LocalDateTime localDateTime = LocalDateTime.parse(dateString, TIME_FORMATTER);
return Date.valueOf(localDateTime.toLocalDate());
}
}

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.ximatai.muyun.domain;
package net.ximatai.muyun.model;

public class OrderColumn {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.ximatai.muyun.domain;
package net.ximatai.muyun.model;

import java.util.List;

Expand Down
159 changes: 159 additions & 0 deletions my-core/src/main/java/net/ximatai/muyun/model/QueryItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package net.ximatai.muyun.model;

public class QueryItem {

private String field;
private String label;
private String alias;

private SymbolType symbolType;

private boolean isMain = true; //ui
private boolean isReference = false;
private boolean isDate = false;
private boolean isTime = false;
private boolean isDatetime = false;
private boolean isBoolean = false;
private boolean isHide = false; //ui
private boolean isNotNull = false;

private Object defaultValue; //ui

public QueryItem of(String field) {
QueryItem item = new QueryItem();
item.field = field;
item.alias = field;
item.symbolType = SymbolType.EQUAL;

if (field.startsWith("t_")) {
item.isDatetime = true;
} else if (field.startsWith("d_")) {
item.isDate = true;
} else if (field.startsWith("b_")) {
item.isBoolean = true;
}

return item;
}

public enum SymbolType {
EQUAL, NOT_EQUAL, LIKE, IN, NOT_IN, RANGE
}

public QueryItem setField(String field) {
this.field = field;
return this;
}

public QueryItem setLabel(String label) {
this.label = label;
return this;
}

public QueryItem setAlias(String alias) {
this.alias = alias;
return this;
}

public QueryItem setSymbolType(SymbolType symbolType) {
this.symbolType = symbolType;
return this;
}

public QueryItem setMain(boolean main) {
isMain = main;
return this;
}

public QueryItem setReference(boolean reference) {
isReference = reference;
return this;
}

public QueryItem setDate(boolean date) {
isDate = date;
return this;
}

public QueryItem setTime(boolean time) {
isTime = time;
return this;
}

public QueryItem setDatetime(boolean datetime) {
isDatetime = datetime;
return this;
}

public QueryItem setBoolean(boolean aBoolean) {
isBoolean = aBoolean;
return this;
}

public QueryItem setHide(boolean hide) {
isHide = hide;
return this;
}

public QueryItem setNotNull(boolean notNull) {
isNotNull = notNull;
return this;
}

public QueryItem setDefaultValue(Object defaultValue) {
this.defaultValue = defaultValue;
return this;
}

public String getField() {
return field;
}

public String getLabel() {
return label;
}

public String getAlias() {
return alias;
}

public SymbolType getSymbolType() {
return symbolType;
}

public boolean isMain() {
return isMain;
}

public boolean isReference() {
return isReference;
}

public boolean isDate() {
return isDate;
}

public boolean isTime() {
return isTime;
}

public boolean isDatetime() {
return isDatetime;
}

public boolean isBoolean() {
return isBoolean;
}

public boolean isHide() {
return isHide;
}

public boolean isNotNull() {
return isNotNull;
}

public Object getDefaultValue() {
return defaultValue;
}
}

0 comments on commit 977740b

Please sign in to comment.