diff --git a/uapbd/src/public/nccloud/api/uapbd/QuerySync.java b/uapbd/src/public/nccloud/api/uapbd/QuerySync.java index 43cff15..fcfdb71 100644 --- a/uapbd/src/public/nccloud/api/uapbd/QuerySync.java +++ b/uapbd/src/public/nccloud/api/uapbd/QuerySync.java @@ -1,12 +1,19 @@ package nccloud.api.uapbd; +import com.alibaba.fastjson.JSONObject; +import nc.bs.dao.BaseDAO; +import nc.bs.dao.DAOException; +import nc.jdbc.framework.processor.ColumnListProcessor; +import nc.jdbc.framework.processor.MapListProcessor; import nccloud.api.rest.utils.IJsonForAPI; import nccloud.api.rest.utils.JsonFactoryForAPI; +import nccloud.api.rest.utils.OpenApiPageInfo; import nccloud.api.rest.utils.ResultMessageUtil; import nccloud.api.rest.utils.vo.ApiDataVO; import nccloud.api.rest.utils.vo.ApiQueryParam; import nccloud.api.rest.utils.vo.ApiUfinterface; +import nccloud.api.uapbd.common.utils.OpenApiPagenationUtils; import nccloud.ws.rest.resource.AbstractNCCRestResource; import org.json.JSONString; @@ -14,10 +21,15 @@ import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import java.util.List; +import java.util.Map; +import java.util.StringJoiner; + @Path("/uapbd/querySync") public class QuerySync extends AbstractNCCRestResource { + public static final BaseDAO BASE_DAO = new BaseDAO(); @Override public String getModule() { return "uapbd"; @@ -51,9 +63,29 @@ public class QuerySync extends AbstractNCCRestResource { } } - private JSONString queryStordoc(ApiUfinterface apiUfinterface) { + private JSONString queryStordoc(ApiUfinterface apiUfinterface) throws DAOException { + Map data = apiUfinterface.getData().getParamdata(); + JSONObject pageInfo = (JSONObject) JSONObject.toJSON(apiUfinterface.getPageInfo()); + data.remove("type"); + String condition = QuerySyncSqlUtils.buildUniversalCondition(data); - return null; + String sql = "SELECT pk_stordoc FROM V_UAPBD_QUERYSYNC_STORDOC WHERE " + condition; + List allPks = (List) BASE_DAO.executeQuery(sql, new ColumnListProcessor()); + OpenApiPageInfo openApiPageInfo = new OpenApiPageInfo(); + String[] currPks = OpenApiPagenationUtils.getCurrentPagePksAndPageInfo(allPks, pageInfo, openApiPageInfo); + + if (currPks == null || currPks.length == 0) { + return ResultMessageUtil.toJSONByPage(new JSONObject[0], openApiPageInfo, false); + } + StringJoiner stringJoiner = new StringJoiner(","); + for (String pk : currPks) { + stringJoiner.add("'" + pk + "'"); + } + String pks = "(" + stringJoiner + ")"; + + List> rows = (List>) BASE_DAO.executeQuery("select * from v_uapbd_querysync_stordoc where pk_stordoc in " + pks, new MapListProcessor()); + + return ResultMessageUtil.toJSONByPage(rows, openApiPageInfo, false); } } \ No newline at end of file diff --git a/uapbd/src/public/nccloud/api/uapbd/QuerySyncSqlUtils.java b/uapbd/src/public/nccloud/api/uapbd/QuerySyncSqlUtils.java new file mode 100644 index 0000000..b914dad --- /dev/null +++ b/uapbd/src/public/nccloud/api/uapbd/QuerySyncSqlUtils.java @@ -0,0 +1,127 @@ +package nccloud.api.uapbd; + + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class QuerySyncSqlUtils { + + /** + * 构建SQL IN子句。 + * 例如:fieldName IN ('value1', 123, NULL) + * 此方法假定传入的 `values` 列表是非空的(由调用方 `buildUniversalCondition` 保证)。 + * + * @param fieldName 字段名 + * @param values 值的列表 (来自非空数组或List) + * @return 构建好的IN子句字符串 + */ + private static String buildInClause(String fieldName, List values) { + String inValues = values.stream() + .map(val -> { + if (val == null) { + return "NULL"; // SQL中的NULL字面量 + } + if (val instanceof String) { + return "'" + escapeSql((String) val) + "'"; + } + if (val instanceof Number || val instanceof Boolean) { + return val.toString(); // 数字和布尔值不需要单引号 + } + // 对于其他类型(例如日期、自定义对象等),默认按其toString()处理,进行转义和加单引号 + return "'" + escapeSql(val.toString()) + "'"; + }) + .collect(Collectors.joining(", ")); // 注意用逗号和空格分隔,更美观 + return fieldName + " IN (" + inValues + ")"; + } + + /** + * 通用构建SQL条件 + * 根据参数Map动态生成SQL WHERE子句的条件部分。 + * - 对于简单值(非null、非空字符串),使用相等匹配 (field = value)。 + * - 对于非空数组或List类型的值,使用IN匹配 (field IN (value1, value2, ...))。 + * - 如果参数值为null、空字符串、空List或空数组,则不处理该字段。 + * - 最终生成的条件会被圆括号包裹。 + * - 如果没有有效的条件生成(例如map为空或所有值都无效),则返回 "(1=1)" 以确保SQL语法正确。 + * + * @param paramMap 参数Map,键为字段名,值为字段值。 + * @return 构建好的SQL条件字符串,例如 "(field1 = 'value1' AND field2 IN ('a', 'b'))" 或 "(1=1)"。 + */ + public static String buildUniversalCondition(Map paramMap) { + if (paramMap == null || paramMap.isEmpty()) { + return "(1=1)"; // 如果参数map本身为null或空,直接返回(1=1) + } + + List conditions = new ArrayList<>(); + + for (Map.Entry entry : paramMap.entrySet()) { + String fieldName = entry.getKey(); + Object value = entry.getValue(); + + // 1. 如果值本身为 null,则不处理此条目 + if (value == null) { + continue; + } + + // 2. 根据值的类型进行处理 + if (value instanceof String) { + String stringValue = (String) value; + if (stringValue.trim().isEmpty()) { // 如果是空字符串(或仅含空格) + continue; // 不处理 + } + conditions.add(fieldName + " = " + formatSqlValue(stringValue)); + } else if (value instanceof List) { + List listValue = (List) value; + if (listValue.isEmpty()) { // 如果列表为空 + continue; // 不处理 + } + conditions.add(buildInClause(fieldName, listValue)); + } else if (value.getClass().isArray()) { + int length = Array.getLength(value); + if (length == 0) { // 如果数组为空 + continue; // 不处理 + } + List arrayAsList = new ArrayList<>(length); + for (int i = 0; i < length; i++) { + arrayAsList.add(Array.get(value, i)); + } + conditions.add(buildInClause(fieldName, arrayAsList)); // 数组元素已转为List处理 + } else { + // 其他非null、非空字符串、非空集合/数组的类型(例如数字、布尔值、日期等) + // formatSqlValue 会处理它们的格式化 + conditions.add(fieldName + " = " + formatSqlValue(value)); + } + } + + if (conditions.isEmpty()) { + return "(1=1)"; // 如果没有收集到任何有效条件,返回(1=1) + } + + return "(" + String.join(" AND ", conditions) + ")"; // 用AND连接并用括号包裹 + } + + private static String escapeSql(String value) { + return value == null ? null : value.replace("'", "''"); + } + + /** + * 格式化SQL查询中的单个值,用于相等条件。 + * 此方法假定传入的 `value` 非null且(如果是字符串)非空 + * + * @param value 要格式化的值 (不为null) + * @return 格式化后的SQL值字符串 + */ + private static String formatSqlValue(Object value) { + // value 在这里保证不为null + if (value instanceof String) { + // 空字符串的检查已在 buildUniversalCondition 中完成 + return "'" + escapeSql((String) value) + "'"; + } else if (value instanceof Number || value instanceof Boolean) { + return value.toString(); // 数字和布尔值直接使用其字符串表示,不加单引号 + } + return "'" + escapeSql(value.toString()) + "'"; + } + +}