From ffdc33229dd044a7a22681e88e37a4942415c3c8 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sat, 7 May 2022 22:47:53 +0800 Subject: [PATCH 001/540] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8574d809..236292a55 100644 --- a/README.md +++ b/README.md @@ -460,7 +460,7 @@ https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md [apijson-framework](https://github.com/APIJSON/apijson-framework) APIJSON 服务端框架,通过数据库表配置角色权限、参数校验等,简化使用 -[apijson-router](https://github.com/APIJSON/apijson-router) APIJSON 的路由插件,对外暴露类 RESTful 接口,内部转成 APIJSON 接口执行 +[apijson-router](https://github.com/APIJSON/apijson-router) APIJSON 的路由插件,可控地对公网暴露类 RESTful 简单接口,内部转成 APIJSON 格式请求来执行。 [apijson-column](https://github.com/APIJSON/apijson-column) APIJSON 的字段插件,支持 字段名映射 和 !key 反选字段 From be268dc5a028a9f8fe0148e7b3bd52dcbc8590e6 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sun, 8 May 2022 01:22:38 +0800 Subject: [PATCH 002/540] Update README.md --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 236292a55..5b36395a1 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,31 @@ https://github.com/Tencent/APIJSON/wiki * **工程轻量小巧** (仅依赖 fastjson,Jar 仅 280KB,Java 文件仅 59 个共 13719 行代码,例如 APIJSONORM 4.3.1) * **多年持续迭代** (自 2016 年开源至今已连续维护 5 年多,累计 2000+ Commits、80+ Releases,不断更新迭代中...) +![image](https://user-images.githubusercontent.com/5738175/167264836-9c5d8f8a-99e1-4e1e-9864-e8f906b8e704.png) + +### 用户反馈 +**腾讯 IEG 数据产品开发组负责人 xinlin:** +“腾讯的 APIJSON 开源方案,它可以做到零代码生成接口和文档,并且整个生成过程是自动化。当企业有元数据的时候,马上就可以获得接口” + +**腾讯科技 后台开发高级工程师 雷大锤:** +“可以抽出时间来看apijson了,这个可以为T10做准备,也是业界很火的东西,可以提升个人影响力!” + +**腾讯 bodian520:** +“在调试GET、POST、PUT接口时遇到了一些问题,把个人的摸索经验分享一下,希望作者能梳理下文档,方便我们更好的接入” + +**华为 minshiwu:** +“demo工程,默认使用apijson-framework,可以做到无任何配置即可体验apijson的各种能力。” + +**百度智慧城市研发 lpeng:** +“很兴奋的发现APIJSON很适合我们的一个开发场景,作为我们协议定义的一部分” + +**中兴工程师 duyijiang:** +“感谢腾讯大大提供的框架,很好用” + +https://github.com/Tencent/APIJSON/issues/132#issuecomment-1106669540 + +
+ ### 常见问题 #### 1.如何定制业务逻辑? 在后端编写 远程函数,可以拿到 session、version、当前 JSON 对象、参数名称 等,然后对查到的数据自定义处理
From 19706c6fa5eef31bfd3854c0ea475945638c2954 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Sun, 8 May 2022 01:25:55 +0800 Subject: [PATCH 003/540] =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=8E=A8=E8=8D=90?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E8=85=BE=E8=AE=AF=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=E7=99=BE=E4=B8=87=E6=95=B0=E6=8D=AE=206s=20=E5=93=8D=E5=BA=94?= =?UTF-8?q?=EF=BC=8CAPIJSON=20=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=83=8C=E5=90=8E=E7=9A=84=E6=95=85=E4=BA=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://my.oschina.net/tommylemon/blog/5375645 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5b36395a1..f37bea636 100644 --- a/README.md +++ b/README.md @@ -435,6 +435,8 @@ https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md [APIJSON对接分布式HTAP数据库TiDB](https://asktug.com/t/htap-tidb/395) +[腾讯业务百万数据 6s 响应,APIJSON 性能优化背后的故事](https://my.oschina.net/tommylemon/blog/5375645) + [APIJSON教程(一):上手apijson项目,学习apijson语法,并实现持久层配置](https://zhuanlan.zhihu.com/p/375681893) [apijson简单demo](https://blog.csdn.net/dmw412724/article/details/113558115) From beac8231a65899741f3a973524253ffe75da8509 Mon Sep 17 00:00:00 2001 From: Montos <1367654518@qq.com> Date: Tue, 10 May 2022 00:20:06 +0800 Subject: [PATCH 004/540] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9LocalDateTim?= =?UTF-8?q?e=E7=B1=BB=E5=9E=8B=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加对LocalDateTime类型支持 --- APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java index cd705a88a..a02bd79b0 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java @@ -19,6 +19,7 @@ import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -879,6 +880,9 @@ else if (value instanceof Date) { else if (value instanceof Time) { value = ((Time) value).toString(); } + else if (value instanceof LocalDateTime) { + value = ((LocalDateTime) value).toString(); + } else if (value instanceof String && isJSONType(config, rsmd, columnIndex, lable)) { //json String castToJson = true; } From 89accdacdc24fabaa6c9527931fe475cccedb71b Mon Sep 17 00:00:00 2001 From: ysy Date: Sun, 29 May 2022 11:20:48 +0800 Subject: [PATCH 005/540] fastjson up2 2.0.4 --- APIJSONORM/pom.xml | 4 ++-- APIJSONORM/src/main/java/apijson/JSON.java | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/APIJSONORM/pom.xml b/APIJSONORM/pom.xml index c1bdf23dc..3f776fb6a 100755 --- a/APIJSONORM/pom.xml +++ b/APIJSONORM/pom.xml @@ -5,7 +5,7 @@ apijson.orm apijson-orm - 5.1.0 + 5.1.0-F2 jar APIJSONORM @@ -21,7 +21,7 @@ com.alibaba fastjson - 1.2.79 + 2.0.4 javax.activation diff --git a/APIJSONORM/src/main/java/apijson/JSON.java b/APIJSONORM/src/main/java/apijson/JSON.java index 28c124cab..a5b501ead 100755 --- a/APIJSONORM/src/main/java/apijson/JSON.java +++ b/APIJSONORM/src/main/java/apijson/JSON.java @@ -64,18 +64,20 @@ public static String getCorrectJson(String s, boolean isArray) { * @param json * @return */ + private static final Feature[] DEFAULT_FASTJSON_FEATURES = {Feature.OrderedField, Feature.AllowSingleQuotes, Feature.DisableCircularReferenceDetect, Feature.UseBigDecimal, Feature.UseObjectArray}; public static Object parse(Object obj) { int features = com.alibaba.fastjson.JSON.DEFAULT_PARSER_FEATURE; features |= Feature.OrderedField.getMask(); try { - return com.alibaba.fastjson.JSON.parse(obj instanceof String ? (String) obj : toJSONString(obj), features); + return com.alibaba.fastjson.JSON.parse(obj instanceof String ? (String) obj : toJSONString(obj), DEFAULT_FASTJSON_FEATURES); } catch (Exception e) { Log.i(TAG, "parse catch \n" + e.getMessage()); } return null; } + /**obj转JSONObject - * @param json + * @param obj * @return */ public static JSONObject parseObject(Object obj) { @@ -89,16 +91,17 @@ public static JSONObject parseObject(Object obj) { * @return */ public static JSONObject parseObject(String json) { - int features = com.alibaba.fastjson.JSON.DEFAULT_PARSER_FEATURE; - features |= Feature.OrderedField.getMask(); - return parseObject(json, features); + return parseObject(json, DEFAULT_FASTJSON_FEATURES); } - /**json转JSONObject + + /** + * json转JSONObject + * * @param json * @param features * @return */ - public static JSONObject parseObject(String json, int features) { + public static JSONObject parseObject(String json, Feature... features) { try { return com.alibaba.fastjson.JSON.parseObject(getCorrectJson(json), JSONObject.class, features); } catch (Exception e) { @@ -127,7 +130,7 @@ public static T parseObject(String json, Class clazz) { try { int features = com.alibaba.fastjson.JSON.DEFAULT_PARSER_FEATURE; features |= Feature.OrderedField.getMask(); - return com.alibaba.fastjson.JSON.parseObject(getCorrectJson(json), clazz, features); + return com.alibaba.fastjson.JSON.parseObject(getCorrectJson(json), clazz, DEFAULT_FASTJSON_FEATURES); } catch (Exception e) { Log.i(TAG, "parseObject catch \n" + e.getMessage()); } From 641d9409413b9b8c0cb4bba03bdefce18c25374d Mon Sep 17 00:00:00 2001 From: ysy Date: Sun, 29 May 2022 12:33:57 +0800 Subject: [PATCH 006/540] fix dead loop --- APIJSONORM/src/main/java/apijson/JSON.java | 2 +- .../apijson/orm/AbstractObjectParser.java | 40 +++++++++---------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/APIJSONORM/src/main/java/apijson/JSON.java b/APIJSONORM/src/main/java/apijson/JSON.java index a5b501ead..09dcd058d 100755 --- a/APIJSONORM/src/main/java/apijson/JSON.java +++ b/APIJSONORM/src/main/java/apijson/JSON.java @@ -64,7 +64,7 @@ public static String getCorrectJson(String s, boolean isArray) { * @param json * @return */ - private static final Feature[] DEFAULT_FASTJSON_FEATURES = {Feature.OrderedField, Feature.AllowSingleQuotes, Feature.DisableCircularReferenceDetect, Feature.UseBigDecimal, Feature.UseObjectArray}; + private static final Feature[] DEFAULT_FASTJSON_FEATURES = {Feature.OrderedField, Feature.AllowSingleQuotes, Feature.UseBigDecimal, Feature.UseObjectArray}; public static Object parse(Object obj) { int features = com.alibaba.fastjson.JSON.DEFAULT_PARSER_FEATURE; features |= Feature.OrderedField.getMask(); diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java index bdbb366e7..a034d0e81 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java @@ -5,13 +5,19 @@ package apijson.orm; -import static apijson.JSONObject.KEY_COMBINE; -import static apijson.JSONObject.KEY_DROP; -import static apijson.JSONObject.KEY_TRY; -import static apijson.RequestMethod.POST; -import static apijson.RequestMethod.PUT; -import static apijson.orm.SQLConfig.TYPE_ITEM; +import apijson.JSONResponse; +import apijson.Log; +import apijson.NotNull; +import apijson.RequestMethod; +import apijson.StringUtil; +import apijson.orm.AbstractFunctionParser.FunctionBean; +import apijson.orm.exception.ConflictException; +import apijson.orm.exception.NotExistException; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import javax.activation.UnsupportedDataTypeException; import java.rmi.ServerException; import java.util.ArrayList; import java.util.Arrays; @@ -22,20 +28,12 @@ import java.util.Map.Entry; import java.util.Set; -import javax.activation.UnsupportedDataTypeException; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; - -import apijson.JSONResponse; -import apijson.Log; -import apijson.NotNull; -import apijson.RequestMethod; -import apijson.StringUtil; -import apijson.orm.AbstractFunctionParser.FunctionBean; -import apijson.orm.exception.ConflictException; -import apijson.orm.exception.NotExistException; +import static apijson.JSONObject.KEY_COMBINE; +import static apijson.JSONObject.KEY_DROP; +import static apijson.JSONObject.KEY_TRY; +import static apijson.RequestMethod.POST; +import static apijson.RequestMethod.PUT; +import static apijson.orm.SQLConfig.TYPE_ITEM; /**简化Parser,getObject和getArray(getArrayConfig)都能用 @@ -572,7 +570,7 @@ public JSON onChildParse(int index, String key, JSONObject value) throws Excepti invalidate(); } } - Log.i(TAG, "onChildParse ObjectParser.onParse key = " + key + "; child = " + child); +// Log.i(TAG, "onChildParse ObjectParser.onParse key = " + key + "; child = " + child); return isEmpty ? null : child;//只添加! isChildEmpty的值,可能数据库返回数据不够count } From be00ec44a1e4a56dfa67db68d3deeb06ff895511 Mon Sep 17 00:00:00 2001 From: ysy Date: Sun, 29 May 2022 15:47:55 +0800 Subject: [PATCH 007/540] fix field order --- APIJSONORM/src/main/java/apijson/JSON.java | 39 +++---------------- .../apijson/orm/AbstractObjectParser.java | 2 +- 2 files changed, 6 insertions(+), 35 deletions(-) diff --git a/APIJSONORM/src/main/java/apijson/JSON.java b/APIJSONORM/src/main/java/apijson/JSON.java index 09dcd058d..b610cfc5b 100755 --- a/APIJSONORM/src/main/java/apijson/JSON.java +++ b/APIJSONORM/src/main/java/apijson/JSON.java @@ -6,8 +6,8 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.fastjson2.JSONReader; import java.util.List; @@ -64,12 +64,10 @@ public static String getCorrectJson(String s, boolean isArray) { * @param json * @return */ - private static final Feature[] DEFAULT_FASTJSON_FEATURES = {Feature.OrderedField, Feature.AllowSingleQuotes, Feature.UseBigDecimal, Feature.UseObjectArray}; + private static final JSONReader.Feature[] DEFAULT_FASTJSON_FEATURES = {JSONReader.Feature.FieldBased, JSONReader.Feature.UseBigDecimalForDoubles}; public static Object parse(Object obj) { - int features = com.alibaba.fastjson.JSON.DEFAULT_PARSER_FEATURE; - features |= Feature.OrderedField.getMask(); try { - return com.alibaba.fastjson.JSON.parse(obj instanceof String ? (String) obj : toJSONString(obj), DEFAULT_FASTJSON_FEATURES); + return com.alibaba.fastjson2.JSON.parse(obj instanceof String ? (String) obj : toJSONString(obj), DEFAULT_FASTJSON_FEATURES); } catch (Exception e) { Log.i(TAG, "parse catch \n" + e.getMessage()); } @@ -91,32 +89,7 @@ public static JSONObject parseObject(Object obj) { * @return */ public static JSONObject parseObject(String json) { - return parseObject(json, DEFAULT_FASTJSON_FEATURES); - } - - /** - * json转JSONObject - * - * @param json - * @param features - * @return - */ - public static JSONObject parseObject(String json, Feature... features) { - try { - return com.alibaba.fastjson.JSON.parseObject(getCorrectJson(json), JSONObject.class, features); - } catch (Exception e) { - Log.i(TAG, "parseObject catch \n" + e.getMessage()); - } - return null; - } - - /**JSONObject转实体类 - * @param object - * @param clazz - * @return - */ - public static T parseObject(JSONObject object, Class clazz) { - return parseObject(toJSONString(object), clazz); + return parseObject(json, JSONObject.class); } /**json转实体类 * @param json @@ -128,9 +101,7 @@ public static T parseObject(String json, Class clazz) { Log.e(TAG, "parseObject clazz == null >> return null;"); } else { try { - int features = com.alibaba.fastjson.JSON.DEFAULT_PARSER_FEATURE; - features |= Feature.OrderedField.getMask(); - return com.alibaba.fastjson.JSON.parseObject(getCorrectJson(json), clazz, DEFAULT_FASTJSON_FEATURES); + return com.alibaba.fastjson2.JSON.parseObject(getCorrectJson(json), clazz, DEFAULT_FASTJSON_FEATURES); } catch (Exception e) { Log.i(TAG, "parseObject catch \n" + e.getMessage()); } diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java index a034d0e81..e571cd8b4 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java @@ -425,7 +425,7 @@ else if (value instanceof String) { // //key{}@ getRealKey, 引用赋值路径 String replaceKey = key.substring(0, key.length() - 1); // System.out.println("getObject key.endsWith(@) >> parseRelation = " + parseRelation); - String targetPath = AbstractParser.getValuePath(type == TYPE_ITEM ? path : parentPath, new String((String) value)); + String targetPath = AbstractParser.getValuePath(type == TYPE_ITEM ? path : parentPath, (String) value); //先尝试获取,尽量保留缺省依赖路径,这样就不需要担心路径改变 Object target = onReferenceParse(targetPath); From 3ed76c34a3fb700c45463e47664a7614a200b2f2 Mon Sep 17 00:00:00 2001 From: huangcanjia Date: Thu, 2 Jun 2022 13:07:17 +0800 Subject: [PATCH 008/540] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=A4=9A?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=8F=82=E4=B8=8Ejoin=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=E5=91=BD=E4=B8=AD=E7=BC=93=E5=AD=98=E8=80=8C?= =?UTF-8?q?=E5=87=BA=E7=8E=B0=E7=9A=841+N=E6=9F=A5=E8=AF=A2=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在缓存副表数据到ChildMap时,反向遍历onList集合,避免除了idKey,userKey之外的字段在putWhere时,跟前端传参指定的顺序相反,导致没有命中缓存。 - 将onList反转 issue #402 --- APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java index a02bd79b0..1f1d4bd96 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -519,6 +520,7 @@ else if (config.isClickHouse() && (sqlTable.startsWith("`") || sqlTable.startsWi if (viceConfig != null) { //FIXME 只有和主表关联才能用 item,否则应该从 childMap 查其它副表数据 List onList = curJoin.getOnList(); if (onList != null) { + Collections.reverse(onList); for (On on : onList) { if (on != null) { String ok = on.getOriginKey(); From 6ab88d13d17265bf637c81eda5f1b95239f68dcb Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Wed, 8 Jun 2022 21:16:21 +0800 Subject: [PATCH 009/540] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f37bea636..5b7be0593 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ Tencent is pleased to support the open source community by making APIJSON availa Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
This source code is licensed under the Apache License Version 2.0
+[APIJSON 已加入 腾源会开源摘星计划(WeOpen Star),该计划提供奖励以鼓励你加入我们的社区](https://github.com/weopenprojects/WeOpen-Star/issues/79)

APIJSON From 51f94299189a58e1971913274ffb7769cca216b7 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Wed, 8 Jun 2022 21:24:40 +0800 Subject: [PATCH 010/540] Update CONTRIBUTING.md --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0cb35f97d..e424b7050 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,9 +50,9 @@ ruoranw 提交的 18 个 Commits, 对 APIJSON 做出了 328 增加和 520 处删 Zerounary 提交的 6 个 Commits, 对 APIJSON 做出了 1,104 增加和 1 处删减(截止 2020/11/04 日)。

-APIJSON 持续招募贡献者,即使是在 Issue 中回答问题,或者做一些简单的 Bug Fix ,也会给 APIJSON 带来很大的帮助。
-APIJSON 已开发近 4 年,在此感谢所有开发者对于 APIJSON 的喜欢和支持,希望你能够成为 APIJSON 的核心贡献者,
-加入 APIJSON ,共同打造一个更棒的零代码、全自动、强安全 ORM 库!🍾🎉 +APIJSON 持续招募贡献者,新增功能、修复 Bug、完善文档、修正错误、宣传推广、回答问题等,都能帮助项目及广大用户。
+APIJSON 已开发近 6 年,在此感谢所有开发者对于 APIJSON 的喜欢和支持,希望你能够成为 APIJSON 的核心贡献者,
+加入 APIJSON ,共同打造一个更棒的零代码、全功能、强安全 ORM 库,造福更多前后端开发者!🍾🎉 ### 为什么一定要贡献代码? APIJSON 作为腾讯开源的知名热门项目,贡献代码除了可以给简历加亮点、为面试加分,还可以避免你碰到以下麻烦:
From f8a3c6706b9dec303e8802ccb8caaf740a3ebc5d Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Wed, 8 Jun 2022 21:25:42 +0800 Subject: [PATCH 011/540] Update CONTRIBUTING.md --- CONTRIBUTING.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e424b7050..939328aa7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,21 +61,6 @@ APIJSON 作为腾讯开源的知名热门项目,贡献代码除了可以给简 3.你需要自己维护你的代码,每次升级 APIJSON 版本时,你都需要下载 APIJSON 新代码再合并你自己的更改
#### 所以为了让你自己的更改始终能跟上项目版本,得到他人给予的可靠且持续的维护,强烈建议 [提交 Pull Request](/CONTRIBUTING.md#pull-request) 来贡献代码。 -​ - -## Issue 提交 - -#### 对于贡献者 - -在提 Issue 前请确保满足一下条件: - -- 必须是一个 Bug 或者功能新增。 -- 必须是 APIJSON 相关问题。 -- 已经在 Issue 中搜索过,并且没有找到相似的 Issue 或者解决方案。 -- 完善下面模板中的信息 - -如果已经满足以上条件,我们提供了 Issue 的标准模版,请按照模板填写。 - ​ ## Pull Request @@ -145,3 +130,19 @@ https://www.jianshu.com/p/00cf29d2d66c

如何在 Github 上给别人的项目贡献代码
https://git-scm.com/book/zh/v2/GitHub-%E5%AF%B9%E9%A1%B9%E7%9B%AE%E5%81%9A%E5%87%BA%E8%B4%A1%E7%8C%AE + + +​ + +## Issue 提交 + +#### 对于贡献者 + +在提 Issue 前请确保满足一下条件: + +- 必须是一个 Bug 或者功能新增。 +- 必须是 APIJSON 相关问题。 +- 已经在 Issue 中搜索过,并且没有找到相似的 Issue 或者解决方案。 +- 完善下面模板中的信息 + +如果已经满足以上条件,我们提供了 Issue 的标准模版,请按照模板填写。 From 9fb6c885f0f5d493bf160e8f60762266823e838c Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Fri, 10 Jun 2022 17:24:11 +0800 Subject: [PATCH 012/540] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5b7be0593..a9f52add0 100644 --- a/README.md +++ b/README.md @@ -219,8 +219,8 @@ https://github.com/Tencent/APIJSON/issues/36
### 注意事项 -请求参数 JSON 中表名、字段名、关键词及对应的值都是大小写敏感、逗号敏感、分号敏感、空格敏感、换行敏感,
-大部分情况都不允许空格和换行,表名以大写字母开头,不要想当然,请严格按照 [设计规范](https://github.com/Tencent/APIJSON/blob/master/Document.md#3) 来调用 API +**请求参数 JSON 中表名、字段名、关键词及对应的值都是大小写敏感、逗号敏感、分号敏感、空格敏感、换行敏感,
+大部分情况都不允许空格和换行,表名以大写字母开头,不要想当然,请严格按照 [设计规范](https://github.com/Tencent/APIJSON/blob/master/Document.md#3) 来调用 API !** [#181](https://github.com/Tencent/APIJSON/issues/181)

From ed935c1c4ad32157cf35ab91a0752985c14bfc73 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Fri, 10 Jun 2022 17:27:56 +0800 Subject: [PATCH 013/540] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a9f52add0..17777f3a1 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ APIJSON 是一种专为 API 而生的 JSON 网络传输协议 以及 基于这
#### APIAuto 展示 APIJSON -使用 APIAuto-机器学习接口工具 来管理和测试 HTTP API 可大幅提升接口联调效率
+**使用 APIAuto-机器学习接口工具 来管理和测试 HTTP API 可大幅 减少传参错误、提升联调效率**
(注意网页工具界面是 APIAuto,里面的 URL+JSON 才是 APIJSON 的 HTTP API):

From 0600a8e93436b0ac60ca8f18c9c02176287b6434 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Fri, 10 Jun 2022 18:50:31 +0800 Subject: [PATCH 014/540] Update --bug.md --- .github/ISSUE_TEMPLATE/--bug.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/--bug.md b/.github/ISSUE_TEMPLATE/--bug.md index 3683b0f3e..35df8dccd 100755 --- a/.github/ISSUE_TEMPLATE/--bug.md +++ b/.github/ISSUE_TEMPLATE/--bug.md @@ -4,6 +4,12 @@ about: Create a report to help us improve --- +如果你已经知道问题所在、怎么解决,请直接提交 Pull Request 为社区做贡献谢谢,开源要大家参与贡献才会更美好。
+开发者也是人,也需要工作和休息,养活自己和家人,也会有心情不好和身体病痛,往往没有额外的时间精力顾及一些小问题,请理解和支持~ +https://github.com/Tencent/APIJSON/issues/406 + +_________________________________ + **提 bug 请发请求和响应的【完整截屏】,没图的自行解决! 开发者有限的时间和精力主要放在【维护项目源码和文档】上! 【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!! From e2826242b89291ecd0505efe7aa61eb8f1eef1d5 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Fri, 10 Jun 2022 18:57:52 +0800 Subject: [PATCH 015/540] Update --bug.md --- .github/ISSUE_TEMPLATE/--bug.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/--bug.md b/.github/ISSUE_TEMPLATE/--bug.md index 35df8dccd..193baa055 100755 --- a/.github/ISSUE_TEMPLATE/--bug.md +++ b/.github/ISSUE_TEMPLATE/--bug.md @@ -4,8 +4,9 @@ about: Create a report to help us improve --- -如果你已经知道问题所在、怎么解决,请直接提交 Pull Request 为社区做贡献谢谢,开源要大家参与贡献才会更美好。
-开发者也是人,也需要工作和休息,养活自己和家人,也会有心情不好和身体病痛,往往没有额外的时间精力顾及一些小问题,请理解和支持~ +如果你已经知道问题所在、怎么解决,请直接提交 Pull Request 为社区做贡献,非常感谢。 +开发者也是人,也需要工作、休息、恋爱、养活自己、陪伴家人等,也有心情不好和身体病痛, +往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~ https://github.com/Tencent/APIJSON/issues/406 _________________________________ From bd3dc264f234f4834c3296c3f3bfd327d5e2165e Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Fri, 10 Jun 2022 18:58:19 +0800 Subject: [PATCH 016/540] Update --bug.md --- .github/ISSUE_TEMPLATE/--bug.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/--bug.md b/.github/ISSUE_TEMPLATE/--bug.md index 193baa055..c752ac3d0 100755 --- a/.github/ISSUE_TEMPLATE/--bug.md +++ b/.github/ISSUE_TEMPLATE/--bug.md @@ -4,9 +4,9 @@ about: Create a report to help us improve --- -如果你已经知道问题所在、怎么解决,请直接提交 Pull Request 为社区做贡献,非常感谢。 -开发者也是人,也需要工作、休息、恋爱、养活自己、陪伴家人等,也有心情不好和身体病痛, -往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~ +如果你已经知道问题所在、怎么解决,请直接提交 Pull Request 为社区做贡献,非常感谢。
+开发者也是人,也需要工作、休息、恋爱、养活自己、陪伴家人等,也有心情不好和身体病痛,
+往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~
https://github.com/Tencent/APIJSON/issues/406 _________________________________ From d95a1b90c8ead2e6a5d2b0f219b5795b706532e2 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Fri, 10 Jun 2022 18:58:59 +0800 Subject: [PATCH 017/540] Update --bug.md --- .github/ISSUE_TEMPLATE/--bug.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/--bug.md b/.github/ISSUE_TEMPLATE/--bug.md index c752ac3d0..1bb8e0264 100755 --- a/.github/ISSUE_TEMPLATE/--bug.md +++ b/.github/ISSUE_TEMPLATE/--bug.md @@ -4,9 +4,9 @@ about: Create a report to help us improve --- -如果你已经知道问题所在、怎么解决,请直接提交 Pull Request 为社区做贡献,非常感谢。
-开发者也是人,也需要工作、休息、恋爱、养活自己、陪伴家人等,也有心情不好和身体病痛,
-往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~
+如果你已经知道问题所在、怎么解决,请直接提交 Pull Request 为社区做贡献,非常感谢。 +开发者也是人,也需要工作、休息、恋爱、养活自己、陪伴家人等,也有心情不好和身体病痛, +往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~ https://github.com/Tencent/APIJSON/issues/406 _________________________________ From 88d895d0f06911693e1b6289a00a8a1ca51f3341 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Fri, 10 Jun 2022 19:00:54 +0800 Subject: [PATCH 018/540] Update --bug.md --- .github/ISSUE_TEMPLATE/--bug.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/--bug.md b/.github/ISSUE_TEMPLATE/--bug.md index 1bb8e0264..545c06b9c 100755 --- a/.github/ISSUE_TEMPLATE/--bug.md +++ b/.github/ISSUE_TEMPLATE/--bug.md @@ -4,9 +4,9 @@ about: Create a report to help us improve --- -如果你已经知道问题所在、怎么解决,请直接提交 Pull Request 为社区做贡献,非常感谢。 -开发者也是人,也需要工作、休息、恋爱、养活自己、陪伴家人等,也有心情不好和身体病痛, -往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~ +如果你已经知道问题所在、怎么解决,请直接 提交 Pull Request 为社区做贡献,非常感谢。 +开发者也是人,也需要工作、休息、恋爱、陪伴家人、走亲访友等,也有心情不好和身体病痛, +往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~ https://github.com/Tencent/APIJSON/issues/406 _________________________________ From f4d63d1799f160c32390b462ea4e68ee2c7ac422 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Fri, 10 Jun 2022 19:08:23 +0800 Subject: [PATCH 019/540] Update --bug.md --- .github/ISSUE_TEMPLATE/--bug.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/--bug.md b/.github/ISSUE_TEMPLATE/--bug.md index 545c06b9c..ec35b18dc 100755 --- a/.github/ISSUE_TEMPLATE/--bug.md +++ b/.github/ISSUE_TEMPLATE/--bug.md @@ -7,6 +7,7 @@ about: Create a report to help us improve 如果你已经知道问题所在、怎么解决,请直接 提交 Pull Request 为社区做贡献,非常感谢。 开发者也是人,也需要工作、休息、恋爱、陪伴家人、走亲访友等,也有心情不好和身体病痛, 往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~ +少数个人的热情终有被耗尽的一天,只有大家共同建设和繁荣社区,才能让开源可持续发展! https://github.com/Tencent/APIJSON/issues/406 _________________________________ From 76c91a9557c34a9b187fee1befedc5a8c36b0c6a Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Fri, 10 Jun 2022 19:09:12 +0800 Subject: [PATCH 020/540] Update --bug.md --- .github/ISSUE_TEMPLATE/--bug.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/--bug.md b/.github/ISSUE_TEMPLATE/--bug.md index ec35b18dc..072aba60f 100755 --- a/.github/ISSUE_TEMPLATE/--bug.md +++ b/.github/ISSUE_TEMPLATE/--bug.md @@ -5,7 +5,7 @@ about: Create a report to help us improve --- 如果你已经知道问题所在、怎么解决,请直接 提交 Pull Request 为社区做贡献,非常感谢。 -开发者也是人,也需要工作、休息、恋爱、陪伴家人、走亲访友等,也有心情不好和身体病痛, +开发者也是人,也需要工作、休息、恋爱、陪伴家人、走亲会友等,也有心情不好和身体病痛, 往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~ 少数个人的热情终有被耗尽的一天,只有大家共同建设和繁荣社区,才能让开源可持续发展! https://github.com/Tencent/APIJSON/issues/406 From 0a764540fdaf5cd80ec79728604080087d29bb78 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Thu, 23 Jun 2022 23:45:26 +0800 Subject: [PATCH 021/540] Update Document.md --- Document.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Document.md b/Document.md index fefcd5eae..afc131f5a 100644 --- a/Document.md +++ b/Document.md @@ -409,7 +409,7 @@ DELETE:
删除数据 | base_url/delete/ | {
   TableName:{< 存储过程 | "@key()":"SQL函数表达式",函数表达式为
function(key0,key1...)
会调用后端数据库对应的存储过程 SQL函数
function(String key0, String key1...)
除了参数会提前赋值,其它和 远程函数 一致 | ["@limit":10,
"@offset":0,
"@procedure()":"getCommentByUserId(id,@limit,@offset)"](http://apijson.cn:8080/get/{"User":{"@limit":10,"@offset":0,"@procedure()":"getCommentByUserId(id,@limit,@offset)"}})
会转为
`getCommentByUserId(38710,10,0)`
来调用存储过程 SQL 函数
`getCommentByUserId(IN id bigint, IN limit int, IN offset int)`
然后变为
"procedure":{
   "count":-1,
   "update":false,
   "list":[]
}
其中 count 是指写操作影响记录行数,-1 表示不是写操作;update 是指是否为写操作(增删改);list 为返回结果集 引用赋值 | "key@":"key0/key1/.../refKey",引用路径为用/分隔的字符串。以/开头的是缺省引用路径,从声明key所处容器的父容器路径开始;其它是完整引用路径,从最外层开始。
被引用的refKey必须在声明key的上面。如果对refKey的容器指定了返回字段,则被引用的refKey必须写在@column对应的值内,例如 "@column":"refKey,key1,..." | ["Moment":{
   "userId":38710
},
"User":{
   "id@":"/Moment/userId"
}](http://apijson.cn:8080/get/{"Moment":{"userId":38710},"User":{"id@":"%252FMoment%252FuserId"}})
User内的id引用了与User同级的Moment内的userId,
即User.id = Moment.userId,请求完成后
"id@":"/Moment/userId" 会变成 "id":38710 子查询 | "key@":{
   "range":"ALL",
   "from":"Table",
   "Table":{ ... }
}
其中:
range 可为 ALL,ANY;
from 为目标表 Table 的名称;
@ 后面的对象类似数组对象,可使用 count 和 join 等功能。 | ["id@":{
   "from":"Comment",
   "Comment":{
      "@column":"min(userId)"
   }
}](http://apijson.cn:8080/get/{"User":{"id@":{"from":"Comment","Comment":{"@column":"min(userId)"}}}})
WHERE id=(SELECT min(userId) FROM Comment) - 模糊搜索 | "key$":"SQL搜索表达式" => "key$":["SQL搜索表达式"],任意SQL搜索表达式字符串,如 %key%(包含key), key%(以key开始), %k%e%y%(包含字母k,e,y) 等,%表示任意字符 | ["name$":"%m%"](http://apijson.cn:8080/get/{"User[]":{"count":3,"User":{"name$":"%2525m%2525"}}}),对应SQL是`name LIKE '%m%'`,查询name包含"m"的一个User数组 + 模糊搜索 | `"key$":"SQL搜索表达式"` => `"key$":["SQL搜索表达式"]`,任意SQL搜索表达式字符串,如 %key%(包含key), key%(以key开始), %k%e%y%(包含字母k,e,y) 等,%表示任意字符 | ["name$":"%m%"](http://apijson.cn:8080/get/{"User[]":{"count":3,"User":{"name$":"%2525m%2525"}}}),对应SQL是`name LIKE '%m%'`,查询name包含"m"的一个User数组 正则匹配 | "key~":"正则表达式" => "key~":["正则表达式"],任意正则表达式字符串,如 ^[0-9]+$ ,*~ 忽略大小写,可用于高级搜索 | ["name~":"^[0-9]+$"](http://apijson.cn:8080/get/{"User[]":{"count":3,"User":{"name~":"^[0-9]%252B$"}}}),对应SQL是`name REGEXP '^[0-9]+$'`,查询name中字符全为数字的一个User数组 连续范围 | "key%":"start,end" => "key%":["start,end"],其中 start 和 end 都只能为 Boolean, Number, String 中的一种,如 "2017-01-01,2019-01-01" ,["1,90000", "82001,100000"] ,可用于连续范围内的筛选 | ["date%":"2017-10-01,2018-10-01"](http://apijson.cn:8080/get/{"User[]":{"count":3,"User":{"date%2525":"2017-10-01,2018-10-01"}}}),对应SQL是`date BETWEEN '2017-10-01' AND '2018-10-01'`,查询在2017-10-01和2018-10-01期间注册的用户的一个User数组 新建别名 | "name:alias",name映射为alias,用alias替代name。可用于 column,Table,SQL函数 等。只用于GET类型、HEAD类型的请求 | ["@column":"toId:parentId"](http://apijson.cn:8080/get/{"Comment":{"@column":"id,toId:parentId","id":51}}),对应SQL是`toId AS parentId`,将查询的字段toId变为parentId返回 From 4dfd9d4d4fa1b5a524634580cc8beed60027bdf9 Mon Sep 17 00:00:00 2001 From: huangcanjia Date: Wed, 6 Jul 2022 18:51:20 +0800 Subject: [PATCH 022/540] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E8=B7=A8?= =?UTF-8?q?=E5=B1=82=E7=BA=A7app=20join?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化app join模式下,一对多join表查询时的1+N性能问题 - 支持客户端join字段,path的多层路径指定 - Join类增加count字段,以支持在生成副表sql时,按照指定count数量生成 - 处理App Join的查询结果时,将'一条条缓存'调整为'攒一起再缓存',防止错误替换 --- .../main/java/apijson/orm/AbstractParser.java | 18 +++++++++---- .../java/apijson/orm/AbstractSQLConfig.java | 2 +- .../java/apijson/orm/AbstractSQLExecutor.java | 26 +++++++++++-------- .../src/main/java/apijson/orm/Join.java | 8 ++++++ 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java index 5135a7279..c472ceb80 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java @@ -1457,10 +1457,11 @@ else if (join != null){ // } path = path.substring(index + 1); - index = path.indexOf("/"); + index = path.lastIndexOf("/"); String tableKey = index < 0 ? path : path.substring(0, index); // User:owner apijson.orm.Entry entry = Pair.parseEntry(tableKey, true); - String table = entry.getKey(); // User + String[] tablePath = entry.getKey().split("/"); // User + String table = tableKey = tablePath[tablePath.length - 1]; // path最后一级为真实table;如:@/A/b/id@,b为目录最后一级 if (StringUtil.isName(table) == false) { throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中 value 的 Table 值 " + table + " 不合法!" + "必须为 &/Table0, onList = new ArrayList<>(); for (Entry refEntry : refSet) { @@ -1656,7 +1664,7 @@ else if (join != null){ if (refObj.size() != tableObj.size()) { // 把 key 强制放最前,AbstractSQLExcecutor 中 config.putWhere 也是放尽可能最前 refObj.putAll(tableObj); - request.put(tableKey, refObj); + parentPathObj.put(tableKey, refObj); // tableObj.clear(); // tableObj.putAll(refObj); diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java index c9c9c8623..cfe4df81d 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java @@ -5008,7 +5008,7 @@ public static SQLConfig parseJoin(RequestMethod method, SQLCo alias = j.getAlias(); //JOIN子查询不能设置LIMIT,因为ON关系是在子查询后处理的,会导致结果会错误 SQLConfig joinConfig = newSQLConfig(method, table, alias, j.getRequest(), null, false, callback); - SQLConfig cacheConfig = j.canCacheViceTable() == false ? null : newSQLConfig(method, table, alias, j.getRequest(), null, false, callback).setCount(1); + SQLConfig cacheConfig = j.canCacheViceTable() == false ? null : newSQLConfig(method, table, alias, j.getRequest(), null, false, callback).setCount(j.getCount()); if (j.isAppJoin() == false) { //除了 @ APP JOIN,其它都是 SQL JOIN,则副表要这样配置 if (joinConfig.getDatabase() == null) { diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java index 1f1d4bd96..fb5713be3 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java @@ -260,7 +260,9 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws Log.i(TAG, ">>> execute result = getCache('" + sql + "', " + position + ") = " + result); if (result != null) { cachedSQLCount ++; - + if (getCache(sql,config).size() > 1) { + result.put(KEY_RAW_LIST, getCache(sql,config)); + } Log.d(TAG, "\n\n execute result != null >> return result;" + "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"); return result; } @@ -589,19 +591,17 @@ else if (curJoin.isOuterJoin() || curJoin.isAntiJoin()) { if (isHead == false) { // @ APP JOIN 查询副表并缓存到 childMap <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - - executeAppJoin(config, resultList, childMap); + Map> appJoinChildMap = new HashMap<>(); + executeAppJoin(config, resultList, appJoinChildMap); // @ APP JOIN 查询副表并缓存到 childMap >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //子查询 SELECT Moment.*, Comment.id 中的 Comment 内字段 - Set> set = childMap.entrySet(); + Set>> set = appJoinChildMap.entrySet(); // - for (Entry entry : set) { - List l = new ArrayList<>(); - l.add(entry.getValue()); - putCache(entry.getKey(), l, null); + for (Entry> entry : set) { + putCache(entry.getKey(), entry.getValue(), null); } putCache(sql, resultList, config); @@ -633,7 +633,7 @@ else if (curJoin.isOuterJoin() || curJoin.isAntiJoin()) { * @param childMap * @throws Exception */ - protected void executeAppJoin(SQLConfig config, List resultList, Map childMap) throws Exception { + protected void executeAppJoin(SQLConfig config, List resultList, Map> childMap) throws Exception { List joinList = config.getJoinList(); if (joinList != null) { @@ -737,8 +737,12 @@ protected void executeAppJoin(SQLConfig config, List resultList, Map } } cacheSql = cc.getSQL(false); - childMap.put(cacheSql, result); - + List results = childMap.get(cacheSql); + if (results == null) { + results = new ArrayList<>(); + childMap.put(cacheSql,results); + } + results.add(result); Log.d(TAG, ">>> executeAppJoin childMap.put('" + cacheSql + "', result); childMap.size() = " + childMap.size()); } } diff --git a/APIJSONORM/src/main/java/apijson/orm/Join.java b/APIJSONORM/src/main/java/apijson/orm/Join.java index 4fb34b0a9..af3c2979e 100644 --- a/APIJSONORM/src/main/java/apijson/orm/Join.java +++ b/APIJSONORM/src/main/java/apijson/orm/Join.java @@ -22,6 +22,7 @@ public class Join { private String joinType; // "@" - APP, "<" - LEFT, ">" - RIGHT, "*" - CROSS, "&" - INNER, "|" - FULL, "!" - OUTER, "^" - SIDE, "(" - ANTI, ")" - FOREIGN private String table; // User private String alias; // owner + private int count = 1; // 当app join子表,需要返回子表的行数,默认1行; private List onList; // ON User.id = Moment.userId AND ... private JSONObject request; // { "id@":"/Moment/userId" } @@ -39,6 +40,13 @@ public void setPath(String path) { this.path = path; } + public int getCount() { + return count; + } + public void setCount(int count) { + this.count = count; + } + public String getJoinType() { return joinType; } From 5525eab38d5c3886a93d082102835b08ad338979 Mon Sep 17 00:00:00 2001 From: TommyLemon <1184482681@qq.com> Date: Thu, 7 Jul 2022 05:52:44 +0800 Subject: [PATCH 023/540] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=AF=B9=20APP=20JOI?= =?UTF-8?q?N=20=E5=90=8C=E5=B1=82=E5=92=8C=E8=B7=A8=E5=B1=82=E7=9A=84?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=EF=BC=9B=E5=AE=8C=E5=96=84=E5=AF=B9=20APP=20?= =?UTF-8?q?JOIN=20=E7=9A=84=20SQL=20=E6=89=A7=E8=A1=8C=E4=B8=8E=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E6=AC=A1=E6=95=B0=E7=BB=9F=E8=AE=A1=EF=BC=9B=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E5=90=8C=E5=B1=82=20JOIN=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=9A=84=E6=8A=A5=E9=94=99=20bug=EF=BC=9B=E8=A7=A3=E5=86=B3=20?= =?UTF-8?q?APP=20JOIN=20=E5=89=AF=E8=A1=A8=E8=BF=94=E5=9B=9E=E5=86=85?= =?UTF-8?q?=E9=83=A8=E5=AD=97=E6=AE=B5=20@RAW@LIST=EF=BC=9Bfastjson2=20?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=201.2.79?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIJSONORM/pom.xml | 2 +- APIJSONORM/src/main/java/apijson/JSON.java | 9 +- .../apijson/orm/AbstractObjectParser.java | 20 +-- .../main/java/apijson/orm/AbstractParser.java | 160 +++++++++++------- .../java/apijson/orm/AbstractSQLExecutor.java | 159 +++++++++-------- 5 files changed, 202 insertions(+), 148 deletions(-) diff --git a/APIJSONORM/pom.xml b/APIJSONORM/pom.xml index 3f776fb6a..fcc4ffa63 100755 --- a/APIJSONORM/pom.xml +++ b/APIJSONORM/pom.xml @@ -21,7 +21,7 @@ com.alibaba fastjson - 2.0.4 + 1.2.79 javax.activation diff --git a/APIJSONORM/src/main/java/apijson/JSON.java b/APIJSONORM/src/main/java/apijson/JSON.java index b610cfc5b..40ef46f9c 100755 --- a/APIJSONORM/src/main/java/apijson/JSON.java +++ b/APIJSONORM/src/main/java/apijson/JSON.java @@ -6,8 +6,9 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.serializer.SerializerFeature; -import com.alibaba.fastjson2.JSONReader; +import com.alibaba.fastjson.JSONReader; import java.util.List; @@ -64,10 +65,10 @@ public static String getCorrectJson(String s, boolean isArray) { * @param json * @return */ - private static final JSONReader.Feature[] DEFAULT_FASTJSON_FEATURES = {JSONReader.Feature.FieldBased, JSONReader.Feature.UseBigDecimalForDoubles}; + private static final Feature[] DEFAULT_FASTJSON_FEATURES = {Feature.OrderedField, Feature.UseBigDecimal}; public static Object parse(Object obj) { try { - return com.alibaba.fastjson2.JSON.parse(obj instanceof String ? (String) obj : toJSONString(obj), DEFAULT_FASTJSON_FEATURES); + return com.alibaba.fastjson.JSON.parse(obj instanceof String ? (String) obj : toJSONString(obj), DEFAULT_FASTJSON_FEATURES); } catch (Exception e) { Log.i(TAG, "parse catch \n" + e.getMessage()); } @@ -101,7 +102,7 @@ public static T parseObject(String json, Class clazz) { Log.e(TAG, "parseObject clazz == null >> return null;"); } else { try { - return com.alibaba.fastjson2.JSON.parseObject(getCorrectJson(json), clazz, DEFAULT_FASTJSON_FEATURES); + return com.alibaba.fastjson.JSON.parseObject(getCorrectJson(json), clazz, DEFAULT_FASTJSON_FEATURES); } catch (Exception e) { Log.i(TAG, "parseObject catch \n" + e.getMessage()); } diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java index e571cd8b4..68b31a87e 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java @@ -71,7 +71,7 @@ public AbstractObjectParser setParser(AbstractParser parser) { * @param parentPath * @param request * @param name - * @throws Exception + * @throws Exception */ public AbstractObjectParser(@NotNull JSONObject request, String parentPath, SQLConfig arrayConfig , boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception { @@ -400,7 +400,7 @@ public boolean onParse(@NotNull String key, @NotNull Object value) throws Except if (arrObj == null) { throw new IllegalArgumentException("子查询 " + path + "/" + key + ":{ from:value } 中 value 对应的主表对象 " + from + ":{} 不存在!"); } - // + // SQLConfig cfg = (SQLConfig) arrObj.get(AbstractParser.KEY_CONFIG); if (cfg == null) { throw new NotExistException(TAG + ".onParse cfg == null"); @@ -453,7 +453,7 @@ else if (value instanceof String) { // //key{}@ getRealKey, 引用赋值路径 Log.d(TAG, "onParse isTable(table) == false >> return true;"); return true;//舍去,对Table无影响 } - } + } //直接替换原来的key@:path为key:target Log.i(TAG, "onParse >> key = replaceKey; value = target;"); @@ -517,7 +517,7 @@ else if (isTable && key.startsWith("@") && JSONRequest.TABLE_KEY_LIST.contains(k /** * @param key * @param value - * @param isFirst + * @param isFirst * @return * @throws Exception */ @@ -553,7 +553,7 @@ public JSON onChildParse(int index, String key, JSONObject value) throws Excepti + "数组 []:{} 中每个 key:{} 都必须是表 TableKey:{} 或 数组 arrayKey[]:{} !"); } - if ( //避免使用 "test":{"Test":{}} 绕过限制,实现查询爆炸 isTableKey && + if ( //避免使用 "test":{"Test":{}} 绕过限制,实现查询爆炸 isTableKey && (arrayConfig == null || arrayConfig.getPosition() == 0)) { objectCount ++; int maxObjectCount = parser.getMaxObjectCount(); @@ -577,7 +577,7 @@ public JSON onChildParse(int index, String key, JSONObject value) throws Excepti - //TODO 改用 MySQL json_add,json_remove,json_contains 等函数! + //TODO 改用 MySQL json_add,json_remove,json_contains 等函数! /**PUT key:[] * @param key * @param array @@ -757,7 +757,7 @@ public AbstractObjectParser executeSQL() throws Exception { //执行SQL操作数据库 if (isTable == false) {//提高性能 sqlReponse = new JSONObject(sqlRequest); - } + } else { try { sqlReponse = onSQLExecute(); @@ -896,7 +896,8 @@ public JSONObject onSQLExecute() throws Exception { result = parser.executeSQL(sqlConfig, isSubquery); boolean isSimpleArray = false; - List rawList = null; + // 提取并缓存数组主表的列表数据 + List rawList = (List) result.remove(AbstractSQLExecutor.KEY_RAW_LIST); if (isArrayMainTable && position == 0 && result != null) { @@ -905,8 +906,7 @@ public JSONObject onSQLExecute() throws Exception { && (childMap == null || childMap.isEmpty()) && (table.equals(arrayTable)); - // 提取并缓存数组主表的列表数据 - rawList = (List) result.remove(AbstractSQLExecutor.KEY_RAW_LIST); + // APP JOIN 副表时副表返回了这个字段 rawList = (List) result.remove(AbstractSQLExecutor.KEY_RAW_LIST); if (rawList != null) { String arrayPath = parentPath.substring(0, parentPath.lastIndexOf("[]") + 2); diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java index c472ceb80..3f598df1d 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java @@ -6,6 +6,7 @@ package apijson.orm; import static apijson.JSONObject.KEY_EXPLAIN; +import static apijson.JSONObject.KEY_JSON; import static apijson.RequestMethod.GET; import java.io.UnsupportedEncodingException; @@ -80,7 +81,7 @@ public abstract class AbstractParser implements Parser, Par public static int MAX_OBJECT_COUNT = 5; public static int MAX_ARRAY_COUNT = 5; public static int MAX_QUERY_DEPTH = 5; - + @Override public int getDefaultQueryCount() { return DEFAULT_QUERY_COUNT; @@ -122,13 +123,13 @@ public AbstractParser() { this(null); } /**needVerify = true - * @param requestMethod null ? requestMethod = GET + * @param method null ? requestMethod = GET */ public AbstractParser(RequestMethod method) { this(method, true); } /** - * @param requestMethod null ? requestMethod = GET + * @param method null ? requestMethod = GET * @param needVerify 仅限于为服务端提供方法免验证特权,普通请求不要设置为 false ! 如果对应Table有权限也建议用默认值 true,保持和客户端权限一致 */ public AbstractParser(RequestMethod method, boolean needVerify) { @@ -136,7 +137,7 @@ public AbstractParser(RequestMethod method, boolean needVerify) { setMethod(method); setNeedVerify(needVerify); } - + protected boolean isRoot = true; public boolean isRoot() { return isRoot; @@ -145,7 +146,7 @@ public AbstractParser setRoot(boolean isRoot) { this.isRoot = isRoot; return this; } - + @NotNull protected Visitor visitor; @@ -464,7 +465,7 @@ public JSONObject parseResponse(JSONObject request) { try { queryDepth = 0; executedSQLDuration = 0; - + requestObject = onObjectParse(request, null, null, null, false); onCommit(); @@ -486,7 +487,7 @@ public JSONObject parseResponse(JSONObject request) { if (Log.DEBUG) { res.put("sql:generate|cache|execute|maxExecute", getSQLExecutor().getGeneratedSQLCount() + "|" + getSQLExecutor().getCachedSQLCount() + "|" + getSQLExecutor().getExecutedSQLCount() + "|" + getMaxSQLCount()); res.put("depth:count|max", queryDepth + "|" + getMaxQueryDepth()); - + executedSQLDuration += sqlExecutor.getExecutedSQLDuration() + sqlExecutor.getSqlResultDuration(); long parseDuration = duration - executedSQLDuration; res.put("time:start|duration|end|parse|sql", startTime + "|" + duration + "|" + endTime + "|" + parseDuration + "|" + executedSQLDuration); @@ -551,7 +552,7 @@ public void onVerifyRole(@NotNull SQLConfig config) throws Exception { /**解析请求JSONObject * @param request => URLDecoder.decode(request, UTF_8); * @return - * @throws Exception + * @throws Exception */ @NotNull public static JSONObject parseRequest(String request) throws Exception { @@ -624,7 +625,7 @@ public static JSONObject wrapRequest(RequestMethod method, String tag, JSONObjec String arrKey = key + "[]"; if (target.containsKey(arrKey) == false) { - target.put(arrKey, new JSONArray()); + target.put(arrKey, new JSONArray()); } try { @@ -680,7 +681,7 @@ public static JSONObject newResult(int code, String msg) { public static JSONObject newResult(int code, String msg, boolean isRoot) { return extendResult(null, code, msg, isRoot); } - + /**添加JSONObject的状态内容,一般用于错误提示结果 * @param object * @param code @@ -702,13 +703,13 @@ public static JSONObject extendResult(JSONObject object, int code, String msg, b + " \n | \n 常见问题:https://github.com/Tencent/APIJSON/issues/36" + " \n 通用文档:https://github.com/Tencent/APIJSON/blob/master/Document.md" + " \n 视频教程:https://search.bilibili.com/all?keyword=APIJSON"); - + msg = index >= 0 ? msg.substring(0, index) : msg; - + if (object == null) { object = new JSONObject(true); } - + if (object.containsKey(JSONResponse.KEY_OK) == false) { object.put(JSONResponse.KEY_OK, JSONResponse.isSuccess(code)); } @@ -720,12 +721,12 @@ public static JSONObject extendResult(JSONObject object, int code, String msg, b if (m.isEmpty() == false) { msg = m + " ;\n " + StringUtil.getString(msg); } - + object.put(JSONResponse.KEY_MSG, msg); if (debug != null) { object.put("debug:info|help", debug); } - + return object; } @@ -758,7 +759,7 @@ public static JSONObject newSuccessResult() { public static JSONObject newSuccessResult(boolean isRoot) { return newResult(JSONResponse.CODE_SUCCESS, JSONResponse.MSG_SUCCEED, isRoot); } - + /**添加请求成功的状态内容 * @param object * @param e @@ -872,7 +873,7 @@ public static JSONObject newErrorResult(Exception e, boolean isRoot) { int code; if (e instanceof UnsupportedEncodingException) { code = JSONResponse.CODE_UNSUPPORTED_ENCODING; - } + } else if (e instanceof IllegalAccessException) { code = JSONResponse.CODE_ILLEGAL_ACCESS; } @@ -890,7 +891,7 @@ else if (e instanceof NotLoggedInException) { } else if (e instanceof TimeoutException) { code = JSONResponse.CODE_TIME_OUT; - } + } else if (e instanceof ConflictException) { code = JSONResponse.CODE_CONFLICT; } @@ -921,10 +922,8 @@ else if (e instanceof NullPointerException) { //TODO 启动时一次性加载Request所有内容,作为初始化。 /**获取正确的请求,非GET请求必须是服务器指定的 - * @param method - * @param request * @return - * @throws Exception + * @throws Exception */ @Override public JSONObject parseCorrectRequest() throws Exception { @@ -1027,13 +1026,14 @@ public JSONObject getStructure(@NotNull String table, String method, String tag, // protected SQLConfig itemConfig; /**获取单个对象,该对象处于parentObject内 - * @param parentPath parentObject的路径 - * @param name parentObject的key - * @param request parentObject的value - * @param config for array item - * @return - * @throws Exception - */ + * @param request parentObject 的 value + * @param parentPath parentObject 的路径 + * @param name parentObject 的 key + * @param arrayConfig config for array item + * @param isSubquery 是否为子查询 + * @return + * @throws Exception + */ @Override public JSONObject onObjectParse(final JSONObject request , String parentPath, String name, final SQLConfig arrayConfig, boolean isSubquery) throws Exception { @@ -1093,7 +1093,7 @@ public JSONObject onObjectParse(final JSONObject request if (type == SQLConfig.TYPE_ITEM_CHILD_0 && query != JSONRequest.QUERY_TABLE && position == 0) { //TODO 应在这里判断 @column 中是否有聚合函数,而不是 AbstractSQLConfig.getColumnString - + JSONObject rp; Boolean compat = arrayConfig.getCompat(); if (compat != null && compat) { @@ -1192,7 +1192,7 @@ public JSONObject onObjectParse(final JSONObject request * @param parentPath parentObject的路径 * @param name parentObject的key * @param request parentObject的value - * @return + * @return * @throws Exception */ @Override @@ -1283,7 +1283,7 @@ public JSONArray onArrayParse(JSONObject request, String parentPath, String name String[] childKeys = StringUtil.split(childPath, "-", false); if (childKeys == null || childKeys.length <= 0 || request.containsKey(childKeys[0]) == false) { childKeys = null; - } + } else if (childKeys.length == 1 && JSONRequest.isTableKey(childKeys[0])) { // 可能无需提取,直接返回 rawList 即可 arrTableKey = childKeys[0]; } @@ -1402,12 +1402,12 @@ else if (childKeys.length == 1 && JSONRequest.isTableKey(childKeys[0])) { // JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_ORDER); JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_RAW); } - + /**JOIN 多表同时筛选 * @param join "&/User,0"} * @param request - * @return - * @throws Exception + * @return + * @throws Exception */ private List onJoinParse(Object join, JSONObject request) throws Exception { JSONObject joinMap = null; @@ -1440,7 +1440,7 @@ else if (join != null){ // 分割 /Table/key String path = e == null ? null : e.getKey(); Object outer = path == null ? null : e.getValue(); - + if (outer instanceof JSONObject == false) { throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中value不合法!" + "必须为 &/Table0/key0, entry = Pair.parseEntry(tableKey, true); - String[] tablePath = entry.getKey().split("/"); // User - String table = tableKey = tablePath[tablePath.length - 1]; // path最后一级为真实table;如:@/A/b/id@,b为目录最后一级 + int index2 = tableKey.lastIndexOf("/"); + String arrKey = index2 < 0 ? null : tableKey.substring(0, index2); + if (arrKey != null && JSONRequest.isArrayKey(arrKey) == false) { + throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 对应的 " + arrKey + " 不是合法的数组 key[] !" + + "@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中不能有 join: value 键值对!"); + } + + tableKey = index2 < 0 ? tableKey : tableKey.substring(index2+1); + + apijson.orm.Entry entry = Pair.parseEntry(tableKey, true); + String table = entry.getKey(); // User if (StringUtil.isName(table) == false) { throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中 value 的 Table 值 " + table + " 不合法!" + "必须为 &/Table0,> tableSet = tableObj.entrySet(); // 取出所有 join 条件 JSONObject requestObj = new JSONObject(true); // (JSONObject) obj.clone(); @@ -1538,7 +1565,19 @@ else if (join != null){ apijson.orm.Entry te = tk == null || p.substring(ind2 + 1).indexOf("/") >= 0 ? null : Pair.parseEntry(tk, true); if (te != null && JSONRequest.isTableKey(te.getKey()) && request.get(tk) instanceof JSONObject) { - refObj.put(k, v); + if (isAppJoin) { + if (refObj.size() >= 1) { + throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":" + e.getKey() + " 中 " + k + " 不合法!" + + "@ APP JOIN 必须有且只有一个引用赋值键值对!"); + } + + if (StringUtil.isName(k.substring(0, k.length() - 1)) == false) { + throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 中 " + k + " 不合法 !" + + "@ APP JOIN 只允许 key@:/Table/refKey 这种 = 等价连接!"); + } + } + + refObj.put(k, v); continue; } } @@ -1585,8 +1624,9 @@ else if (join != null){ j.setAlias(alias); j.setOuter((JSONObject) outer); j.setRequest(requestObj); - if (parentPathObj != null) { - j.setCount(parentPathObj.getInteger("count") != null ? parentPathObj.getInteger("count") : 1); + if (arrKey != null) { + Integer count = parentPathObj.getInteger(JSONRequest.KEY_COUNT); + j.setCount(count == null ? getDefaultQueryCount() : count); } List onList = new ArrayList<>(); @@ -1598,7 +1638,7 @@ else if (join != null){ throw new IllegalArgumentException(e.getKey() + ":value 中 value 值 " + targetPath + " 不合法!必须为引用赋值的路径 '/targetTable/targetKey' !"); } - // 取出引用赋值路径 targetPath 对应的 Table 和 key + // 取出引用赋值路径 targetPath 对应的 Table 和 key index = targetPath.lastIndexOf("/"); String targetKey = index < 0 ? null : targetPath.substring(index + 1); if (StringUtil.isName(targetKey) == false) { @@ -1638,24 +1678,24 @@ else if (join != null){ if (targetObj == null) { throw new IllegalArgumentException(e.getKey() + ":'/targetTable/targetKey' 中路径对应的对象 '" + targetTableKey + "':{} 不存在或值为 null !必须是 {} 这种 JSONObject 格式!"); } - + Join.On on = new Join.On(); on.setKeyAndType(j.getJoinType(), j.getTable(), originKey); if (StringUtil.isName(on.getKey()) == false) { throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中 value 的 key@ 中 key 值 " + on.getKey() + " 不合法!必须满足英文单词变量名格式!"); } - + on.setOriginKey(originKey); on.setOriginValue((String) refEntry.getValue()); on.setTargetTable(targetTable); on.setTargetAlias(targetAlias); on.setTargetKey(targetKey); - + onList.add(on); } - + j.setOnList(onList); - + joinList.add(j); // onList.add(table + "." + key + " = " + targetTable + "." + targetKey); // ON User.id = Moment.userId @@ -1762,7 +1802,7 @@ public static String replaceArrayChildPath(String parentPath, String valuePath) pos = ps[i+1].contains("/") == false ? ps[i+1] : ps[i+1].substring(0, ps[i+1].indexOf("/")); if ( - //StringUtil.isNumer(pos) && + //StringUtil.isNumer(pos) && vs[i+1].startsWith(pos + "/") == false) { vs[i+1] = pos + "/" + vs[i+1]; } diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java index fb5713be3..1dcbb7544 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java @@ -65,14 +65,14 @@ public int getCachedSQLCount() { public int getExecutedSQLCount() { return executedSQLCount; } - + private long executedSQLDuration = 0; private long sqlResultDuration = 0; @Override public long getExecutedSQLDuration() { return executedSQLDuration; } - + @Override public long getSqlResultDuration() { return sqlResultDuration; @@ -95,7 +95,7 @@ public void putCache(String sql, List list, SQLConfig config) { Log.i(TAG, "saveList sql == null || list == null >> return;"); return; } - + cacheMap.put(sql, list); } @@ -165,7 +165,7 @@ public ResultSet execute(@NotNull Statement statement, String sql) throws Except @Override public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws Exception { long executedSQLStartTime = System.currentTimeMillis(); - + boolean isPrepared = config.isPrepared(); final String sql = config.getSQL(false); @@ -212,7 +212,7 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws if (isExplain == false) { executedSQLDuration += System.currentTimeMillis() - executedSQLStartTime; } - + result = new JSONObject(true); result.put(JSONResponse.KEY_COUNT, updateCount); result.put("update", updateCount >= 0); @@ -241,7 +241,7 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws //id,id{}至少一个会有,一定会返回,不用抛异常来阻止关联写操作时前面错误导致后面无条件执行! result.put(JSONResponse.KEY_COUNT, updateCount);//返回修改的记录数 - + String idKey = config.getIdKey(); if (config.getId() != null) { result.put(idKey, config.getId()); @@ -249,7 +249,7 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws if (config.getIdIn() != null) { result.put(idKey + "[]", config.getIdIn()); } - + return result; case GET: @@ -271,7 +271,7 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws executedSQLCount ++; executedSQLStartTime = System.currentTimeMillis(); } - rs = executeQuery(config); //FIXME SQL Server 是一次返回两个结果集,包括查询结果和执行计划,需要 moreResults + rs = executeQuery(config); //FIXME SQL Server 是一次返回两个结果集,包括查询结果和执行计划,需要 moreResults if (isExplain == false) { executedSQLDuration += System.currentTimeMillis() - executedSQLStartTime; } @@ -318,23 +318,23 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws if (capacity > 100) { // 有 WHERE 条件,条件越多过滤数据越多,暂时不考虑 @combine:"a | (b & !c)" 里面 | OR 和 ! NOT 条件,太复杂也不是很必要 Map> combine = config.getCombineMap(); - + List andList = combine == null ? null : combine.get("&"); int andCondCount = andList == null ? (config.getWhere() == null ? 0 : config.getWhere().size()) : andList.size(); - + List orList = combine == null ? null : combine.get("|"); int orCondCount = orList == null ? 0 : orList.size(); - + List notList = combine == null ? null : combine.get("!"); int notCondCount = notList == null ? 0 : notList.size(); - + // 有 GROUP BY 分组,字段越少过滤数据越多 String[] group = StringUtil.split(config.getGroup()); int groupCount = group == null ? 0 : group.length; if (groupCount > 0 && Arrays.asList(group).contains(config.getIdKey())) { groupCount = 0; } - + // 有 HAVING 聚合函数,字段越多过滤数据越多,暂时不考虑 @combine:"a | (b & !c)" 里面 | OR 和 ! NOT 条件,太复杂也不是很必要 Map having = config.getHaving(); int havingCount = having == null ? 0 : having.size(); @@ -350,7 +350,7 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws } } } - + resultList = new ArrayList<>(capacity); } @@ -363,7 +363,7 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws //