From 242cbf4187bd7b2e52086bc8db8d734173a069da Mon Sep 17 00:00:00 2001 From: cloudAndMonkey Date: Fri, 25 Nov 2022 16:22:23 +0800 Subject: [PATCH 1/5] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 配置描述信息 --- README.md | 1375 ++++++++++++++++++++++++++++------------------------- 1 file changed, 734 insertions(+), 641 deletions(-) diff --git a/README.md b/README.md index fc4f52cab..9e7409bdb 100644 --- a/README.md +++ b/README.md @@ -1,719 +1,812 @@ -Tencent is pleased to support the open source community by making APIJSON available.
-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 -

- -

🏆 零代码、全功能、强安全 ORM 库 🚀
后端接口和文档零代码,前端(客户端) 定制返回 JSON 的数据和结构

- -

- English -  通用文档 - 视频教程 - 在线体验 -

-

- -   -   - - - - - - - - -

-

- - - -   -   -   - -

-

- -   -   -

-

- -   -   -

-

- -   -   - -

- -

- ---- - -导航目录: 项目简介 [上手使用](#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B) [社区生态](#%E6%8A%80%E6%9C%AF%E4%BA%A4%E6%B5%81)      完整详细的导航目录 [点这里查看](/Navigation.md)
- - -APIJSON 是一种专为 API 而生的 JSON 网络传输协议 以及 基于这套协议实现的 ORM 库。
-为各种增删改查提供了完全自动化的万能通用接口,零代码实时满足千变万化的各种新增和变更需求。
-能大幅降低开发和沟通成本,简化开发流程,缩短开发周期。
-适合中小型前后端分离的项目,尤其是 初创项目、内部项目、低代码/零代码、小程序、BaaS、Serverless 等。
- -通过万能通用接口,前端可以定制任何数据、任何结构。
-大部分 HTTP 请求后端再也不用写接口了,更不用写文档了。
-前端再也不用和后端沟通接口或文档问题了。再也不会被文档各种错误坑了。
-后端再也不用为了兼容旧接口写新版接口和文档了。再也不会被前端随时随地没完没了地烦了。 - -### 特点功能 - -#### 对于后端 -* 提供万能通用接口,大部分 HTTP API 不用再写 -* 零代码增删改查、各种跨库连表、JOIN 嵌套子查询等 -* 自动生成文档,不用再编写和维护,且自动静态检查 -* 自动校验权限、自动管理版本、自动防 SQL 注入 -* 开放 HTTP API 无需划分版本,始终保持兼容 - -#### 对于前端 -* 不用再向后端催接口、求文档 -* 数据和结构完全定制,要啥有啥 -* 看请求知结果,所求即所得 -* 可一次获取任何数据、任何结构 -* 能去除多余数据,节省流量提高速度 - -
- -### APIJSON 接口展示 -#### Postman 展示 APIJSON -![](https://static.oschina.net/uploads/img/201711/12230359_f7fQ.jpg) -
- -#### APIAuto 展示 APIJSON -**使用 APIAuto-机器学习接口工具 来管理和测试 HTTP API 可大幅 减少传参错误、提升联调效率**
-(注意网页工具界面是 APIAuto,里面的 URL+JSON 才是 APIJSON 的 HTTP API):
-
-

- APIJSON 多表关联查询、结构自由组合,APIAuto 多个测试账号、一键共享测试用例 -

- -![](https://oscimg.oschina.net/oscnet/up-bbbec4fc5edc472be127c02a4f3cd8f4ec2.JPEG) -![](https://raw.githubusercontent.com/TommyLemon/StaticResources/master/APIJSON/APIJSON_query_associate.gif) - -
-

- APIAuto 自动生成前端(客户端)请求代码 和 Python 测试用例代码,一键下载 -

- -![](https://oscimg.oschina.net/oscnet/up-637193bbd89b41c3264827786319e842aee.JPEG) - -
-

- APIAuto 自动保存请求记录、自动生成接口文档,可添加常用请求、快捷查看一键恢复 -

- -![](https://oscimg.oschina.net/oscnet/up-7dcb4ae71bd3892a909e4ffa37ba7c1d92a.JPEG) - -
-

- APIAuto 一键自动接口回归测试,不需要写任何代码(注解、注释等全都不要) -

+# 功能点 + +### 一个json(事务)同时支持新增、修改、删除、查询、别名 + +https://github.com/Tencent/APIJSON/issues/468 + +#### 使用说明 + +json支持多种方式定义method -![](https://oscimg.oschina.net/oscnet/up-c1ba774f8e7fcc5adcdb05cad5bd414d766.JPEG) +第一种: -
-

- 一图胜千言 - APIJSON 部分基础功能概览 -

+ "@post","@put","@delete","@head","@get","@gets","@head","@heads" -![](https://oscimg.oschina.net/oscnet/up-e21240ef3770326ee6015e052226d0da184.JPEG) -![](https://raw.githubusercontent.com/TommyLemon/StaticResources/master/APIJSON/APIJSON_query_summary.gif) +"@post": ["Moment","Comment[]"] , 值为数组格式, 每个value = key +需要保证每个key唯一, 唯一判断标准: -

+key = Moment -### APIJSON App 演示 -使用 APIJSON + ZBLibrary 开发的 Android 客户端 Demo (以下 Gif 图看起来比较卡,实际上运行很流畅): -
-![](https://oscimg.oschina.net/oscnet/up-a3f167e593080e8a3fc09c3d5fc09330c98.gif) -![](https://oscimg.oschina.net/oscnet/up-141abcb5dabc01c890d70c461bd1fdc751f.gif) -![](https://oscimg.oschina.net/oscnet/up-58aecc2701c2c4ea33e53f246e427773b09.gif) +key= Moment[] -
+会判断为相同key. 请通过别名区分, 别名格式: Sys_user_role:sur xxx表名:别名 -### APIJSON 分享演讲 -#### APIJSON-零代码接口与文档 ORM 库(国际开源谷 Gitee Meetup) +``` +{ + "@post": ["Moment","Comment:cArray[]","User:u"], // 分发到 POST 请求对应的解析处理 + "Moment": { + // TODO 其它字段 + }, + "Comment:cArray[]": [ + { + // TODO 其它字段 + } + ], + "@get": ["User"], // 分发到 GET 请求对应的解析处理 + "User:u": { + // TODO 其它字段 + }, + "Privacy": { // 按 URL 对应的默认方法处理 + // TODO 其它字段 + } +} -https://www.bilibili.com/video/BV1Tv411t74v +对于没有显式声明操作方法的,直接用 URL(/get, /post 等) 对应的默认操作方法 -![image](http://apijson.cn/images/comparison/APIJSON_vs_PreviousWays.jpg) +``` +第二种: -#### APIJSON 和 APIAuto-零代码开发和测试(QECon 全球软件质量&效能大会) +对象内定义"@method": "GET", value大写 -https://www.bilibili.com/video/BV1yv411p7Y4 +``` +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_role", + "Sys_role": { + "@column": "id", + "role_name": "角色1" + } + }, + "Sys_user_role:sur[]": { + "@method": "GET", + "Sys_user_role": { + "role_id{}@": "sql" + } + }, + "Sys_role_permission:srp[]": { + "@method": "GET", + "Sys_role_permission": { + "role_id{}@": "sql" + } + }, + "@explain": true +} +``` -wecom-temp-377bbd0daf5aed716baf7ebcb003d94c +#### 解析顺序 +1) 对象内 "@method" +2) "@post","@put","@delete" +3) 对于没有显式声明操作方法的,直接用 URL(/get, /post 等) 对应的默认操作方法 -
+#### 建议 -### 为什么选择 APIJSON? -前后端 关于接口的 开发、文档、联调 等 10 大痛点解析
-https://github.com/Tencent/APIJSON/wiki +1. 一个json包含不同操作方法, url method 使用 /post, /put +2. value为JSONArray, 建议通过"@post" 方式配置, 如果没有配置,执行 3 -* **解决十大痛点** (可帮前后端开发大幅提振开发效率、强力杜绝联调扯皮、巧妙规避文档缺陷、非常节省流量带宽) -* **开发提速很大** (CRUD 零代码热更新全自动,APIJSONBoot 对比 SSM、SSH 等保守估计可提速 20 倍以上) -* **腾讯官方开源** (使用 GitHub、Gitee、工蜂 等平台的官方账号开源,微信公众号、腾讯云+社区 等官方公告) -* **社区影响力大** (GitHub 1W+ Star 在 350W Java 项目中排名前 120,远超 FLAG, BAT 等国内外绝大部分开源项目) -* **多样用户案例** (腾讯内有互娱、音乐、微信、云与智慧,外部有华为、华能、百度、快手、中兴、圆通、传音等) -* **适用场景广泛** (社交聊天、阅读资讯、影音视频、办公学习 等各种 App、网站、公众号、小程序 等非金融类项目) -* **周边生态丰富** (Android, iOS, Web 等各种 Demo、继承 JSON 的海量生态、零代码 接口测试 和 单元测试 工具等) -* **文档视频齐全** (项目介绍、快速上手、安装部署 等后端、前端、客户端的 图文解说、视频教程、代码注释 等) -* **功能丰富强大** (增删改查、分页排序、分组聚合、各种条件、各种 JOIN、各种子查询、跨库连表 等零代码实现) -* **使用安全简单** (自动增删改查、自动生成文档、自动管理版本、自动控制权限、自动校验参数、自动防 SQL 注入) -* **灵活定制业务** (在后端编写 远程函数,可以拿到 session、version、当前 JSON 对象 等,然后自定义处理) -* **高质可靠代码** (代码严谨规范,商业分析软件源伞 Pinpoint 代码扫描报告平均每行代码 Bug 率低至 0.15%) -* **兼容各种项目** (协议不限 HTTP,与其它库无冲突,对各类 Web 框架集成友好且提供 SpringBoot, JFinal 的示例) -* **工程轻量小巧** (仅依赖 fastjson,Jar 仅 280KB,Java 文件仅 59 个共 13719 行代码,例如 APIJSONORM 4.3.1) -* **多年持续迭代** (自 2016 年起已连续维护 6 年,50+ 个贡献者、90+ 次发版、2900+ 次提交,不断更新迭代中...) +#### Request表 配置说明 -![image](https://user-images.githubusercontent.com/5738175/167264836-9c5d8f8a-99e1-4e1e-9864-e8f906b8e704.png) +这只是我的配置仅供参考, 后续 测试会用到: -### 用户反馈 -**腾讯 IEG 数据产品开发组负责人 xinlin:** -“腾讯的 APIJSON 开源方案,它可以做到零代码生成接口和文档,并且整个生成过程是自动化。当企业有元数据的时候,马上就可以获得接口” +``` +单条新增: +POST User_address {"MUST":"addr","UPDATE": {"@role": "OWNER,ADMIN","childFunTest-()": "childFunTest(addr)"}, "REFUSE": "id"} +批量新增: +POST User_address[] {"User_address[]": [{"MUST":"addr","REFUSE": "id"}], "UPDATE": {"@role": "OWNER,ADMIN","childFunTest-()": "childFunTest(addr)"}} +单条修改: +PUT User_address {"User_address":{ "MUST":"id","REFUSE": "userId", "UPDATE": {"@role": "OWNER,ADMIN","childFunTest-()": "childFunTest(addr)"}} } +批量修改: +PUT User_address[] {"User_address[]": [{"MUST": "id","REFUSE": "userId"}], "UPDATE": {"@role": "OWNER,ADMIN"}} +删除: +DELETE User_address {"User_address":{ "MUST":"id{}","REFUSE": "!", "INSERT": {"@role": "OWNER,ADMIN"}} } -**腾讯科技 后台开发高级工程师 雷大锤:** -“可以抽出时间来看apijson了,这个可以为T10做准备,也是业界很火的东西,可以提升个人影响力!” +``` -**腾讯 bodian520:** -“在调试GET、POST、PUT接口时遇到了一些问题,把个人的摸索经验分享一下,希望作者能梳理下文档,方便我们更好的接入” - -**华为 minshiwu:** -“demo工程,默认使用apijson-framework,可以做到无任何配置即可体验apijson的各种能力。” - -**字节跳动 qiujunlin:** -“初次见到这个项目,觉得太惊艳了,眼前一亮。给我的感受是,项目大大简化了开发流程,开发效率提升了很多倍。” - -**百度智慧城市研发 lpeng:** -“很兴奋的发现APIJSON很适合我们的一个开发场景,作为我们协议定义的一部分” - -**中兴 duyijiang:** -“感谢腾讯大大提供的框架,很好用” - -https://github.com/Tencent/APIJSON/issues/132#issuecomment-1106669540 - -
- -### 常见问题 -#### 1.如何定制业务逻辑? -在后端编写 远程函数,可以拿到 session、version、当前 JSON 对象、参数名称 等,然后对查到的数据自定义处理
-https://github.com/Tencent/APIJSON/issues/101 - -#### 2.如何控制权限? -在 Access 表配置校验规则,默认不允许访问,需要对 每张表、每种角色、每种操作 做相应的配置,粒度细分到行级
-https://github.com/Tencent/APIJSON/issues/12 - -#### 3.如何校验参数? -在 Request 表配置校验规则 structure,提供 MUST、TYPE、VERIFY 等通用方法,可通过 远程函数 来完全自定义
-https://github.com/Tencent/APIJSON/wiki#%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86 - -更多常见问题及提问前必看
-https://github.com/Tencent/APIJSON/issues/36 -
- -### 注意事项 -**请求参数 JSON 中表名、字段名、关键词及对应的值都是大小写敏感、逗号敏感、分号敏感、空格敏感、换行敏感,
-大部分情况都不允许空格和换行,表名以大写字母开头,不要想当然,请严格按照 [设计规范](https://github.com/Tencent/APIJSON/blob/master/Document.md#3) 来调用 API !** -[#181](https://github.com/Tencent/APIJSON/issues/181) -
-
-
-
- -导航目录: [项目简介](#--apijson) 上手使用 [社区生态](#%E6%8A%80%E6%9C%AF%E4%BA%A4%E6%B5%81)      完整详细的导航目录 [点这里查看](/Navigation.md)
- -### 快速上手 - -#### 1.后端上手 -可以跳过这个步骤,直接用APIJSON服务器IP地址 apijson.cn:8080 来测试接口。
-见  [APIJSON后端上手 - Java](https://github.com/APIJSON/APIJSON-Demo/tree/master/APIJSON-Java-Server)
- -#### 2.前端上手 -可以跳过这个步骤,直接使用 [APIAuto-机器学习HTTP接口工具](https://github.com/TommyLemon/APIAuto) 或 下载客户端App。
-见  [Android](https://github.com/APIJSON/APIJSON-Demo/tree/master/APIJSON-Android)  或  [iOS](https://github.com/APIJSON/APIJSON-Demo/tree/master/APIJSON-iOS)  或  [JavaScript](https://github.com/APIJSON/APIJSON-Demo/tree/master/APIJSON-JavaScript)
- - -### 下载客户端 App - -仿微信朋友圈动态实战项目
-[APIJSONApp.apk](http://files.cnblogs.com/files/tommylemon/APIJSONApp.apk) - -测试及自动生成代码工具
-[APIJSONTest.apk](http://files.cnblogs.com/files/tommylemon/APIJSONTest.apk) - -### 开源许可 -使用 [Apache License 2.0](/LICENSE),对 公司、团队、个人 等 商用、非商用 都自由免费且非常友好,请放心使用和登记 - -### 使用登记 -如果您在使用 APIJSON,请让我们知道,您的使用对我们非常重要(新的按登记顺序排列、专群优先答疑解惑):
-https://github.com/Tencent/APIJSON/issues/187 -
- - -
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - * [腾讯科技有限公司](https://www.tencent.com) - * [腾讯音乐娱乐集团](https://www.tencentmusic.com) - * [深圳市传音通讯有限公司](https://www.transsion.com) - * [社宝信息科技(上海)有限公司](https://shebaochina.com) - * [华能贵诚信托有限公司](https://www.hngtrust.com) - * [投投科技](https://www.toutou.com.cn) - * [圆通速递](https://www.yto.net.cn) - * [乐拼科技](https://www.lepinyongche.com) - * [珠海采筑电子商务有限公司](https://www.aupup.com) - * [上海信息出奇科技有限公司](https://www.masscms.com) - * [爱投斯智能技术(深圳)有限公司](http://www.aiotos.net) - -### 贡献者们 -主项目 APIJSON 的贡献者们(6 个腾讯工程师、1 个微软工程师、1 个知乎基础研发架构师、1 个字节跳动工程师、1 个网易工程师、1 个 Zoom 工程师、1 个圆通工程师、1 个智联招聘工程师、1 个美国加州大学学生、3 个 SUSTech 学生等):
-https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -生态周边项目的作者们(2 个腾讯工程师、1 个 BAT 技术专家、1 个微软工程师、2 个字节跳动工程师、1 个神州数码工程师&Apache dubbo2js 作者 等):
-https://github.com/search?o=desc&q=apijson&s=stars&type=Repositories
-https://search.gitee.com/?skin=rec&type=repository&q=apijson&sort=stars_count
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -还有为 APIJSON 扫描代码贡献 Issue 的 [奇安信代码卫士](https://github.com/QiAnXinCodeSafe) 和 [源伞科技](https://www.sourcebrella.com) -
- - -
-
- -感谢大家的贡献。 - -### 统计分析 -国内腾讯、华为、阿里巴巴、美团、字节跳动、百度、京东、网易、快手等 和 国外 Google, Microsoft, Amazon, Paypal, IBM, Shopee 等
-数百名知名大厂员工点了 Star,也有腾讯、华为、字节跳动、Microsoft、Zoom 等不少知名大厂员工提了 PR/Issue,非常感谢大家的支持~
-[![Stargazers over time](https://starchart.cc/Tencent/APIJSON.svg)](https://starchart.cc/Tencent/APIJSON) -image -image -image - - - -### 规划及路线图 -新增功能、强化安全、提高性能、增强稳定、完善文档、丰富周边、推广使用
-https://github.com/Tencent/APIJSON/blob/master/Roadmap.md - -理论上所有支持 SQL 与 JDBC/ODBC 的软件,都可以用本项目对接 CRUD,待测试:
-[Elasticsearch](https://www.elastic.co/cn/what-is/elasticsearch-sql), [OceanBase](https://www.oceanbase.com/docs/oceanbase/V2.2.50/ss-sr-select_daur3l), [Spark](https://spark.apache.org/docs/3.3.0/sql-ref-syntax-qry-select.html)(可用 Hive 对接), [Phoenix](http://phoenix.apache.org/language/index.html#select)(延伸支持 HBase) - -### 我要赞赏 -创作不易,坚持更难,右上角点 ⭐Star 来支持/收藏下吧,谢谢 ^_^
- -
-
-
- -导航目录: [项目简介](#--apijson) [上手使用](#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B) 社区生态      完整详细的导航目录 [点这里查看](/Navigation.md)
- -### 技术交流 -如果有什么问题或建议可以 [填问卷](https://wj.qq.com/s2/10971431/2a09) 或 [提 Issue](https://github.com/Tencent/APIJSON/issues/36),交流技术,分享经验。
-如果你解决了某些 bug,或者新增了一些功能,欢迎 [贡献代码](https://github.com/Tencent/APIJSON/pulls),感激不尽~
-https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md - -**开发者也是人,也需要工作、休息、恋爱、陪伴家人、走亲会友等,也有心情不好和身体病痛,**
-**往往没有额外的时间精力顾及一些小问题,请理解和支持,开源要大家参与贡献才会更美好~**
-**少数个人的热情终有被耗尽的一天,只有大家共同建设和繁荣社区,才能让开源可持续发展!**
+![img](https://tcs-devops.aliyuncs.com/storage/112o42fb67f3226bf1ba31143f8e3983d0d3?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk2MjcxMiwiaWF0IjoxNjY5MzU3OTEyLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm80MmZiNjdmMzIyNmJmMWJhMzExNDNmOGUzOTgzZDBkMyJ9.c0kLsYpkpHzkVchL8ZxzUiPf0uvD3G-dsrIc1_zxBl0) -**QQ 技术群**: 请在常见问题 Issue 中查找
+### 别名 -**开发者时间精力有限,原则上优先解决 登记用户 和 贡献者 的问题,**
-**不解决 文档/视频/常见问题 已明确说明、描述简陋 或 态度无礼 的问题!**
-**如果你已经多次得到帮助,却仍然只索取不贡献,那就别指望大家再帮你!**
-**私聊作者请教技术问题 或者 频繁在互助群 @ 作者 可能会被拉黑/禁言/踢群,请尊重和理解,谢谢!**
+格式: -如果你 [提 PR 登记了自己使用 APIJSON 的公司](https://github.com/Tencent/APIJSON/issues/187),可以加 **企业用户支持专群**,作者亲自且优先答疑,
-作者只有解答完了这个专群里的全部问题,才看情况解答 Issue 里的问题(对 Issue 不保证解答、更不保证及时);
-其它群为互助群,由于大多数问题 在文档/Issue 已有答案却反复提 或者 缺少必要信息要来来回回沟通问清细节 已浪费太多时间,
-甚至有白嫖还把自己当大爷的自私自利伸手党输出情绪,作者不再解答互助群问题,由群友互助解答,建议未登记企业的用户 [填问卷](https://wj.qq.com/s2/10971431/2a09) 或 [提 Issue](https://github.com/Tencent/APIJSON/issues/36)。
+Sys_user_role:sur xxx表名:别名 -如果你为 APIJSON 做出了以下任何一个贡献:
-[提交了 PR 且被合并](https://github.com/Tencent/APIJSON/pull/92)、[提交了优质 Issue](https://github.com/Tencent/APIJSON/issues/189)、[发表了优质文章](https://blog.csdn.net/qq_41829492/article/details/88670940)、[开发了可用的生态项目](https://github.com/zhangchunlin/uliweb-apijson),
-可以在群里发出贡献链接并附带说明,管理员将设置关注你一段时间,优先答疑解惑。
-互助群一般解答顺序:贡献者 > 帮助他人的群友 > 带企业名昵称 > 带岗位名昵称 > 其他群友。 - +Comment:cArray[] -### 相关推荐 -[APIJSON, 让接口和文档见鬼去吧!](https://my.oschina.net/tommylemon/blog/805459) +#### 实现思路 -[腾讯业务百万数据 6s 响应,APIJSON 性能优化背后的故事](https://my.oschina.net/tommylemon/blog/5375645) +当时参考了作者的示例: 注册流程. 看到绕过校验, 可以将多条json语句组装在一起, 批量执行. 于是就想如何实现一个json支持不同操作,并支持事物. -[仿QQ空间和微信朋友圈,高解耦高复用高灵活](https://my.oschina.net/tommylemon/blog/885787) +通过分析源码, 熟悉了校验流程、json解析执行流程、json解析生成sql语句流程、一些兼容、校验规则等 -[后端开挂:3行代码写出8个接口!](https://my.oschina.net/tommylemon/blog/1574430) +经过和作者讨论, 很感谢作者提供了相关解决方案和思路. 逐步理解了apijson的设计原理和框架结构. -[后端自动化版本管理,再也不用改URL了!](https://my.oschina.net/tommylemon/blog/1576587) +一个json(事务)同时支持新增、修改、删除、查询、别名, 实现思路如下: -[3步创建APIJSON后端新表及配置](https://my.oschina.net/tommylemon/blog/889074) +1、校验模块 -[APIJSON对接分布式HTAP数据库TiDB](https://asktug.com/t/htap-tidb/395) +将json解析成对象、临时变量、子查询、别名、tag等 -[APIJSON教程(一):上手apijson项目,学习apijson语法,并实现持久层配置](https://zhuanlan.zhihu.com/p/375681893) +并将method 添加到 json对象属性中. -[apijson简单demo](https://blog.csdn.net/dmw412724/article/details/113558115) +``` +"Sys_role": { + "@method": "PUT", + "id": "6aedce0d-2a29-4fbe-aeed-0ba935ca6b41", + "id{}@": "sql", + "role_code": "code-subrange-4", + "role_name": "角色-subrange-4" + } +``` -[apijson简单使用](https://www.cnblogs.com/greyzeng/p/14311995.html) +2、对象解析 -[APIJSON简单部署和使用](https://blog.csdn.net/m450744192/article/details/108462611) +用对象属性@method , 替换 Parser 的 method -[学习自动化接口APIJSON](https://www.jianshu.com/p/981a2a630c7b) +3、事物支持 -[APIJSON 接口调试实践](https://github.com/Tencent/APIJSON/issues/189) - -[关于APIJSON远程函数](https://mp.weixin.qq.com/s?__biz=Mzg3NTc1NDUyNA==&mid=2247483950&idx=1&sn=b11e70bdf083c55d72238e107449ae2e&chksm=cf3de75df84a6e4b3a4acd0846531b0bd12bc90379523fbaf6b4f900fc3cdc1b1ce3eff97fd9&scene=178&cur_album_id=2548737392338354178#rd) - -[APIJSON新增方法实例](https://cloud.tencent.com/developer/article/2098890) - -[APIJSON-APIJSON的那些事儿](https://cloud.tencent.com/developer/article/2098888) +### 后续优化建议 -[APIJSON-零代码接口和文档 JSON 协议 与 ORM 库](https://cloud.tencent.com/developer/article/2077042) +1、独立定义一个url method, 通过解析不同method执行不同流程 -[APIJSON使用例子总结](https://blog.csdn.net/weixin_41077841/article/details/110518007) +和已有method区分开,避免歧义 -[APIJSON 自动化接口和文档的快速开发神器 (一)](https://blog.csdn.net/qq_41829492/article/details/88670940) +2、最外层新增传参 "transaction": true 来指定开启事务 +目前是url put、post来控制开启事物, 以及提交的时候 在 AbstractParser onCommit 判断 transactionIsolation (4 : 开启事物, 0: 非事物请求) -[APIJSON在mac电脑环境下配置去连接SQL Server](https://juejin.im/post/5e16d21ef265da3e2e4f4956) +![image](https://user-images.githubusercontent.com/12228225/202369747-396a4062-c70d-407e-abfa-c333d4c89bee.png) -[APIJSON复杂业务深入实践(类似12306订票系统)](https://blog.csdn.net/aa330233789/article/details/105309571) +详细实现请参见: https://github.com/Tencent/APIJSON/issues/468 -[全国行政区划数据抓取与处理](https://www.xlongwei.com/detail/21032616) +3、完善 "[@Explain](https://github.com/Explain)" -[新手搭建 APIJSON 项目指北](https://github.com/jerrylususu/apijson_todo_demo/blob/master/FULLTEXT.md) +如果没有执行计划,则返回sql语句. 能够在 reponse返回值中, 看到json中执行的每条sql,方便排错 -[使用APIJSON写低代码Crud接口](https://blog.csdn.net/weixin_42375862/article/details/121654264) - -[apijson在同一个接口调用中 使用远程函数写入更新时间和创建时间](https://blog.csdn.net/qietingfengsong/article/details/124097229) +![img](https://tcs-devops.aliyuncs.com/storage/112oc4589a6d650755c05381097fe9f2294f?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9jNDU4OWE2ZDY1MDc1NWMwNTM4MTA5N2ZlOWYyMjk0ZiJ9.WySq2UEIS5fMySWRqtKiaXzR4wwtQVxrtbSp98vHmx4) -[APIJSON(一:综述)](https://blog.csdn.net/qq_50861917/article/details/120556168) +4、@version支持 -[APIJSON 代码分析(三:demo主体代码)](https://blog.csdn.net/qq_50861917/article/details/120751630) +定义不同场景的 新增、修改、删除等执行规则. 请通过version版本区分 -[APIJSON 代码分析(二)AbstractParser类(解析器)](https://blog.csdn.net/weixin_45767055/article/details/120815927) +Request表是通过tag、method、version来保证唯一. -[APIJSON 代码分析(四:AbstractObjectParser源码阅读)](https://blog.csdn.net/qq_50861917/article/details/120896381) +![image-20221125144359453](/Users/xy/Library/Application Support/typora-user-images/image-20221125144359453.png) -[APIJSON 代码分析 AbstractSQLConfig 第二篇](https://blog.csdn.net/csascscascd/article/details/120684889) +5、前置函数 -[APIJSON 代码分析(六)APIJSON—Verifier检查类](https://blog.csdn.net/weixin_45767055/article/details/121321731) +前置函数能够将json语句, 加入到 当前事物中. -[APIJSON 代码分析(四)AbstractSQLExecutor—SQL执行器](https://blog.csdn.net/weixin_45767055/article/details/121069887) +例如: 像数组一样,解析成每一条语句去执行. - -### 生态项目 -[APIJSON-Demo](https://github.com/APIJSON/APIJSON-Demo) APIJSON 各种语言、各种框架 的 使用示例项目、上手文档、测试数据 SQL 文件 等 +### mysql8 with-as表达式 -[apijson-orm](https://github.com/APIJSON/apijson-orm) APIJSON ORM 库,可通过 Maven, Gradle 等远程依赖 +#### 前提条件 -[apijson-framework](https://github.com/APIJSON/apijson-framework) APIJSON 服务端框架,通过数据库表配置角色权限、参数校验等,简化使用 +1、mysql版本: 8+ -[apijson-router](https://github.com/APIJSON/apijson-router) APIJSON 的路由插件,可控地对公网暴露类 RESTful 简单接口,内部转成 APIJSON 格式请求来执行。 - -[apijson-column](https://github.com/APIJSON/apijson-column) APIJSON 的字段插件,支持 字段名映射 和 !key 反选字段 +2、mysql-connector-java: 8.0.31 -[APIAuto](https://github.com/TommyLemon/APIAuto) 敏捷开发最强大易用的 HTTP 接口工具,机器学习零代码测试、生成代码与静态检查、生成文档与光标悬浮注释 +版本支持 with-as即可 -[UnitAuto](https://github.com/TommyLemon/UnitAuto) 机器学习单元测试平台,零代码、全方位、自动化 测试 方法/函数 的正确性和可用性 +3、druid: 1.2.15 -[SQLAuto](https://github.com/TommyLemon/SQLAuto) 智能零代码自动化测试 SQL 语句执行结果的数据库工具 +版本支持 with-as即可 -[apijson-doc](https://github.com/vincentCheng/apijson-doc) APIJSON 官方文档,提供排版清晰、搜索方便的文档内容展示,包括设计规范、图文教程等 +4、去掉 durid wall配置 -[APIJSONdocs](https://github.com/ruoranw/APIJSONdocs) APIJSON 英文文档,提供排版清晰的文档内容展示,包括详细介绍、设计规范、使用方式等 +delete子查询, druid wall 拦截器报错 sql injection violation -[apijson.org](https://github.com/APIJSON/apijson.org) APIJSON 官方网站,提供 APIJSON 的 功能简介、登记用户、作者与贡献者、相关链接 等 +![image-20221125152519359](/Users/xy/Library/Application Support/typora-user-images/image-20221125152519359.png) -[APIJSON.NET](https://github.com/liaozb/APIJSON.NET) C# 版 APIJSON ,支持 MySQL, PostgreSQL, SQL Server, Oracle, SQLite +#### 测试案例 -[apijson-go](https://github.com/glennliao/apijson-go) Go 版 APIJSON , 基于Go(>=1.18) + GoFrame2, 支持查询、单表增删改、权限管理等 - -[apijson-go](https://gitee.com/tiangao/apijson-go) Go 版 APIJSON ,支持单表查询、数组查询、多表一对一关联查询、多表一对多关联查询 等 +查询单个range ref引用 -[apijson-hyperf](https://github.com/kvnZero/hyperf-APIJSON.git) PHP 版 APIJSON,基于 Hyperf 支持 MySQL +``` +// 测试 mysql8 with as表达式 +// 用户表 +// 用户角色表 +// 角色表 +// 示例一 单个range ref引用 +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_role", + "Sys_role": { + "@column": "id", + "role_name": "角色1" + } + }, + "Sys_user_role:sur[]": { + "@method": "GET", + "Sys_user_role": { + "role_id{}@": "sql" + } + }, + "Sys_role_permission:srp[]": { + "@method": "GET", + "Sys_role_permission": { + "role_id{}@": "sql" + } + }, + "@explain": true +} -[APIJSON-php](https://github.com/xianglong111/APIJSON-php) PHP 版 APIJSON,基于 ThinkPHP,支持 MySQL, PostgreSQL, SQL Server, Oracle 等 +// 第二种写法 +{ + "@get": ["sql@","Sys_user_role:sur[]","Sys_role_permission:srp[]"], + "sql@": { + "with": true, + "from": "Sys_role", + "Sys_role": { + "@column": "id", + "role_name": "角色1" + } + }, + "Sys_user_role:sur[]": { + "Sys_user_role": { + "role_id{}@": "sql" + } + }, + "Sys_role_permission:srp[]": { + "Sys_role_permission": { + "role_id{}@": "sql" + } + }, + "@explain": true +} +``` -[apijson-php](https://github.com/qq547057827/apijson-php) PHP 版 APIJSON,基于 ThinkPHP,支持 MySQL, PostgreSQL, SQL Server, Oracle 等 +mysql8执行结果: -[apijson-node](https://github.com/kevinaskin/apijson-node) 字节跳动工程师开源的 Node.ts 版 APIJSON,提供 nestjs 和 typeorm 的 Demo 及后台管理 +![img](https://tcs-devops.aliyuncs.com/storage/112oc4589a6d650755c05381097fe9f2294f?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9jNDU4OWE2ZDY1MDc1NWMwNTM4MTA5N2ZlOWYyMjk0ZiJ9.WySq2UEIS5fMySWRqtKiaXzR4wwtQVxrtbSp98vHmx4) -[uliweb-apijson](https://github.com/zhangchunlin/uliweb-apijson) Python 版 APIJSON,支持 MySQL, PostgreSQL, SQL Server, Oracle, SQLite 等 +mysql5.7执行结果: -[APIJSONParser](https://github.com/Zerounary/APIJSONParser) 第三方 APIJSON 解析器,将 JSON 动态解析成 SQL +![img](https://tcs-devops.aliyuncs.com/storage/112oa2437cfa419471ebdb7ea62dec97ee21?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9hMjQzN2NmYTQxOTQ3MWViZGI3ZWE2MmRlYzk3ZWUyMSJ9.ulNYQKUnvWMIZCpsc-caImZMsF4h21Vq5WdJ03hwjgc) + +#### 查询多个range ref引用 + +``` +{ "sql@": { "@method": "GET", "with": true, "from": "Sys_role", "Sys_role": { "@column": "id", "role_name": "角色1" } }, "sql_user@": { "@method": "GET", "with": true, "from": "Sys_user", "Sys_user": { "@column": "id", "id": "f0894db2-6940-4d89-a5b2-4405d0ad0c8f" } }, "Sys_user_role:sur[]": { "@method": "GET", "Sys_user_role": { "role_id{}@": "sql", "user_id{}@": "sql_user" } }, "Sys_role_permission:srp[]": { "@method": "GET", "Sys_role_permission": { "role_id{}@": "sql" } }, "@explain": true} + + + + +Plain Text +``` + +mysql8执行结果: + +![img](https://tcs-devops.aliyuncs.com/storage/112o8c94c21ab8f2f473337a53b369ea8db4?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm84Yzk0YzIxYWI4ZjJmNDczMzM3YTUzYjM2OWVhOGRiNCJ9.DoQZ7uoFEoUonbut23NPp_uzVTZ851PlzZ5FlSZWKGY) + +mysql5.7执行结果: + +![img](https://tcs-devops.aliyuncs.com/storage/112o9671ece47b1834ac147cc01cd3900ece?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm85NjcxZWNlNDdiMTgzNGFjMTQ3Y2MwMWNkMzkwMGVjZSJ9.EPqYf1F_RooQF2c5PtrzPdMYCkYZ8Tng4p0Nobgymgc) + +#### delete子查询 + +```j s +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_role_permission", + "Sys_role_permission": { + "@column": "id", + "role_id{}": ["e7129d5f-b07e-4996-9965-9528e370a393"] + } + }, + "Sys_role_permission": { + "@method": "DELETE", + "id{}@": "sql" + }, + "explan": true +} + +``` + +![img](https://tcs-devops.aliyuncs.com/storage/112o12df4490ee563a2a5a36da580823528a?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8xMmRmNDQ5MGVlNTYzYTJhNWEzNmRhNTgwODIzNTI4YSJ9.shAM0ABXqPJTlFYVMU8UjxngUE3jdWgficdNcHgp2Ho) + +mysql8执行sql语句: + +``` +WITH `sql` AS (SELECT `id` FROM `housekeeping`.`Sys_role_permission` WHERE ( (`role_id` IN ('68877ee9-4cf4-4f32-86e6-16c505ca3b21')) ) ) DELETE FROM `housekeeping`.`Sys_role_permission` WHERE ( (`id` IN ( SELECT * FROM `sql`) ) ) + +Plain Text +``` + +mysql5.7执行结果: + +``` +DELETE FROM `housekeeping`.`Sys_role_permission` WHERE ( (`id` IN ( SELECT * FROM (SELECT `id` FROM `housekeeping`.`Sys_role_permission` WHERE ( (`role_id` IN ('20d337bb-9886-455f-8dce-f1cadab0ec4f')) ) ) AS `sql`) ) ) + + + +Plain Text +``` + +#### update子查询 + +``` +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_role_permission", + "Sys_role_permission": { + "@column": "role_id", + "id{}": ["6aedce0d-2a29-4fbe-aeed-0ba935ca6b41"] + } + }, + "Sys_role": { + "@method": "PUT", + "id": "6aedce0d-2a29-4fbe-aeed-0ba935ca6b41", + "id{}@": "sql", + "role_code": "code-subrange-4", + "role_name": "角色-subrange-4" + }, + "@explain": true +} + +第二种写法 +{ + "@get": ["sql@"], + "sql@": { + "with": true, + "from": "Sys_role_permission", + "Sys_role_permission": { + "@column": "role_id", + "id{}": ["c95ef2d6-bf14-42b0-bb87-038cee8c78f1"] + } + }, + "@put": ["Sys_role"], + "Sys_role": { + "id": "0bb92d96-8ca6-469e-91e8-60308ce5b835", + "id{}@": "sql", + "role_code": "code-subrange-4", + "role_name": "角色-subrange-4" + }, + "@explain": true +} +``` + +mysql8执行sql语句: + +![img](https://tcs-devops.aliyuncs.com/storage/112o69fb17f5eb1c109501063a0501e068ef?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm82OWZiMTdmNWViMWMxMDk1MDEwNjNhMDUwMWUwNjhlZiJ9.1lyjMFAM-y9l5Mu6vlgXRv6S0xRwxoMDdrPTzs8LTbQ) + +mysql5.7执行结果: + +![img](https://tcs-devops.aliyuncs.com/storage/112oe59ad49145a7d0a4f100ba717261ee91?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0ODM1MiwiaWF0IjoxNjY5MzQzNTUyLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9lNTlhZDQ5MTQ1YTdkMGE0ZjEwMGJhNzE3MjYxZWU5MSJ9.bOOaskAmRczI9U87uNNIqB1pQxHlkmeZDzYAd_zmaMI) + +#### GETS 单条子查询 + +``` +http://localhost:8675/lowCodePlatform/forms/api/gets + +{ + "sql@": { + "with": true, + "from": "Sys_user_role", + "Sys_user_role": { + "@column": "role_id", + "user_id": "4732209c-5785-4827-b532-5092f154fd94" + } + }, + "Sys_role[]": { + "Sys_role": { + "id{}@": "sql" + }, + "page": 0, + "count": 10, + "query": 2 + }, + "tag":"Sys_role[]", + "total@": "/Sys_role[]/total", + "@explain": true +} + +第二种写法 +{ + "@gets": ["sql@","Sys_role[]"], + "sql@": { + "with": true, + "from": "Sys_user_role", + "Sys_user_role": { + "@column": "role_id", + "user_id": "4732209c-5785-4827-b532-5092f154fd94" + } + }, + "Sys_role[]": { + "Sys_role": { + "id{}@": "sql" + }, + "page": 0, + "count": 10, + "query": 2 + }, + "tag":"Sys_role[]", + "total@": "/Sys_role[]/total", + "@explain": true +} + +``` + +Access、Request需要配置鉴权信息: + +![img](https://tcs-devops.aliyuncs.com/storage/112oc0e2d9666d0e6ae5bba40dd10e86ff8b?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9jMGUyZDk2NjZkMGU2YWU1YmJhNDBkZDEwZTg2ZmY4YiJ9.WiHevTQ80WuelszQxRrsQYWQD4u_60rfj6tsZn9d4vY) + +mysql8执行sql语句: + +![img](https://tcs-devops.aliyuncs.com/storage/112o13624f7ea9b1bbbb31bc4cc83cd96ae6?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8xMzYyNGY3ZWE5YjFiYmJiMzFiYzRjYzgzY2Q5NmFlNiJ9.ZSCMLnTzj7BCi4nxZXSYohKVfHWNR--G5WXv9qE4R1c) + +mysql5.7执行结果: + +![img](https://tcs-devops.aliyuncs.com/storage/112oae3f5de5b703c6334747befb9ab05349?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0ODc5OSwiaWF0IjoxNjY5MzQzOTk5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9hZTNmNWRlNWI3MDNjNjMzNDc0N2JlZmI5YWIwNTM0OSJ9.xVaHGnOULNO4uec94RadSs5K8iG0QZVyGD-FvlNraOY) + +#### GETS多条子查询 + +``` +http://localhost:8675/lowCodePlatform/forms/api/gets + +{ + "sql@": { + "@method": "GETS", + "with": true, + "from": "Sys_role", + "Sys_role": { + "@column": "id", + "role_name": "超级管理员" + } + }, + "sql_user@": { + "@method": "GETS", + "with": true, + "from": "Sys_user", + "Sys_user": { + "@column": "id", + "id": "4732209c-5785-4827-b532-5092f154fd94" + } + }, + "Sys_user_role:sur[]": { + "@method": "GETS", + "Sys_user_role": { + "role_id{}@": "sql", + "user_id{}@": "sql_user" + } + }, + "Sys_role_permission:srp[]": { + "@method": "GETS", + "Sys_role_permission": { + "role_id{}@": "sql" + } + }, + "@explain": true +} + +``` + +mysql8执行sql语句: + +![img](https://tcs-devops.aliyuncs.com/storage/112of22704b782cc932d4f51a144aaddbe76?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9mMjI3MDRiNzgyY2M5MzJkNGY1MWExNDRhYWRkYmU3NiJ9.ejWQb3yK60XBm3zRm4PU077l3lu2jsHjqX5ij0tvS7g) + +mysql5.7执行结果: + +![img](https://tcs-devops.aliyuncs.com/storage/112o331a15eb0b89f8788c2e1369e9ead38a?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0ODg3MSwiaWF0IjoxNjY5MzQ0MDcxLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8zMzFhMTVlYjBiODlmODc4OGMyZTEzNjllOWVhZDM4YSJ9.NZjO2ndpyIW5CdQ3giGL4ylkclWC4VRNtJePIB7hBTs) + +#### head 单个子查询 + +普通获取数量 + +``` +http://localhost:8675/lowCodePlatform/forms/api/head +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_user_role", + "Sys_user_role": { + "@column": "role_id", + "user_id": "4732209c-5785-4827-b532-5092f154fd94" + } + }, + "Sys_role": { + "@method": "head", + "id{}@": "sql" + }, + "@explain": true +} + +``` + +mysql8执行sql语句: + +![img](https://tcs-devops.aliyuncs.com/storage/112o97e7879481ef209d27cd689881ba2dae?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm85N2U3ODc5NDgxZWYyMDlkMjdjZDY4OTg4MWJhMmRhZSJ9.1FsB785CT9VOnKf-Z6NYu6Ouy3DiL0SJm5G0iSHnO94) + +mysql5.7执行结果: + +![img](https://tcs-devops.aliyuncs.com/storage/112o7b2de6f66df479e2b38f53e25da56b04?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0ODk1NywiaWF0IjoxNjY5MzQ0MTU3LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm83YjJkZTZmNjZkZjQ3OWUyYjM4ZjUzZTI1ZGE1NmIwNCJ9.Nxi3u1TMTYE92FuAnz4srLBLeW8fHt-T0gXIOguAu-Q) + +#### head 多个子查询 + +普通获取数量 + +``` +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_role", + "Sys_role": { + "@column": "id", + "role_name": "超级管理员" + } + }, + "sql_user@": { + "@method": "GET", + "with": true, + "from": "Sys_user", + "Sys_user": { + "@column": "id", + "id": "4732209c-5785-4827-b532-5092f154fd94" + } + }, + "Sys_user_role": { + "@method": "HEAD", + "role_id{}@": "sql", + "user_id{}@": "sql_user" + }, + "Sys_role_permission": { + "@method": "HEAD", + "role_id{}@": "sql" + }, + "@explain": true +} + +``` + +mysql8执行sql语句: + +![img](https://tcs-devops.aliyuncs.com/storage/112o2da6826648bb92fe52d292e6f98194fe?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8yZGE2ODI2NjQ4YmI5MmZlNTJkMjkyZTZmOTgxOTRmZSJ9.z9t8h2jF9HYrnr-86j61zQmIuzNquNZ1LWD-mKFyOa8) + +mysql5.7执行结果: + +![img](https://tcs-devops.aliyuncs.com/storage/112o0d8df9fbfdc94b6b6f338f080cd4bc19?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0OTAwOCwiaWF0IjoxNjY5MzQ0MjA4LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8wZDhkZjlmYmZkYzk0YjZiNmYzMzhmMDgwY2Q0YmMxOSJ9.3jOg9eJMTRZXIQh3ZFnTsuhu1N4CnoM3CR7t3I6rIn4) -[FfApiJson](https://gitee.com/own_3_0/ff-api-json) 用 JSON 格式直接生成 SQL,借鉴 APIJSON 支持多数据源 +#### heads 单个子查询 -[APIJSON-ToDo-Demo](https://github.com/jerrylususu/apijson_todo_demo) 一个简单的 todo 示例项目,精简数据,简化上手流程,带自定义鉴权逻辑 +普通获取数量 -[apijson-learn](https://github.com/rainboy-learn/apijson-learn) APIJSON 学习笔记和源码解析 +Access、Request需要配置鉴权信息: -[apijson-practice](https://github.com/vcoolwind/apijson-practice) BAT 技术专家开源的 APIJSON 参数校验注解 Library 及相关 Demo +![img](https://tcs-devops.aliyuncs.com/storage/112oe091e1d4376a6fcb62cbce0383cdddf9?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9lMDkxZTFkNDM3NmE2ZmNiNjJjYmNlMDM4M2NkZGRmOSJ9._BSyl8VzN15CTAxr_J1ud0tzYCBQwGQWqaiBRvmau8Q) -[apijson-db2](https://github.com/andream7/apijson-db2) APIJSON 接入 IBM 数据库 DB2 的 Demo +``` +http://localhost:8675/lowCodePlatform/forms/api/heads -[APIJSONDemo](https://github.com/qiujunlin/APIJSONDemo) 字节跳动工程师接入 ClickHouse 的 APIJSON 使用 Demo - -[APIJSONDemo_ClickHouse](https://github.com/chenyanlann/APIJSONDemo_ClickHouse) APIJSON + SpringBoot 连接 ClickHouse 使用的 Demo - -[APIJSONBoot_Hive](https://github.com/chenyanlann/APIJSONBoot_Hive) APIJSON + SpringBoot 连接 Hive 使用的 Demo - -[apijson-sample](https://gitee.com/greyzeng/apijson-sample) APIJSON 简单使用 Demo 及教程 - -[apijson-examples](https://gitee.com/drone/apijson-examples) APIJSON 的前端、业务后端、管理后端 Demo - -[light4j](https://github.com/xlongwei/light4j) 整合 APIJSON 和微服务框架 light-4j 的 Demo,同时接入了 Redis - -[SpringServer1.2-APIJSON](https://github.com/Airforce-1/SpringServer1.2-APIJSON) 智慧党建服务器端,提供 上传 和 下载 文件的接口 - -[apijson_template](https://github.com/abliger/apijson_template) apijson java 模版,使用 gradle 管理依赖和构建应用 - -[api-json-demo](https://gitee.com/hxdwd/api-json-demo) 基于 APIJSON,实现低代码写 CURD 代码,代替传统 ORM 框架,适配 Oracle 事务 - -[ApiJsonByJFinal](https://gitee.com/zhiyuexin/ApiJsonByJFinal) 整合 APIJSON 和 JFinal 的 Demo - -[apijson-builder](https://github.com/pengxianggui/apijson-builder) 一个方便为 APIJSON 构建 RESTful 请求的 JavaScript 库 - -[AbsGrade](https://github.com/APIJSON/AbsGrade) 列表级联算法,支持微信朋友圈单层评论、QQ空间双层评论、百度网盘多层(无限层)文件夹等 - -[APIJSON-Android-RxJava](https://github.com/TommyLemon/APIJSON-Android-RxJava) 仿微信朋友圈动态实战项目,ZBLibrary(UI) + APIJSON(HTTP) + RxJava(Data) - -[Android-ZBLibrary](https://github.com/TommyLemon/Android-ZBLibrary) Android MVP 快速开发框架,Demo 全面,注释详细,使用简单,代码严谨 - -感谢热心的作者们的贡献,点 ⭐Star 支持下他们吧。 - - -### 腾讯犀牛鸟开源人才培养计划 -https://github.com/Tencent/APIJSON/issues/229 - - -#### qiujunlin **2.接入 presto/hive/clickhouse/db2 任意一个** - -APIJSON 接入 clickhouse 使用demo
-https://github.com/qiujunlin/APIJSONDemo - -#### zhangshukun 2.接入 presto/hive/clickhouse/db2 任意一个 -APIJSON-Demo接入db2
-https://github.com/andream7/apijson-db2 - -#### hanxu 1.完善入门介绍视频 -重构 APIJSON 文档
-https://hanxu2018.github.io/APIJSON-DOC/
-文档源码
-https://github.com/HANXU2018/APIJSON-DOC
-配套评论区 apijson-doc-Comment
-https://github.com/HANXU2018/apijson-doc-Comment - -#### chenyanlan 2.接入 presto/hive/clickhouse/db2 任意一个 -APIJSON + SpringBoot连接ClickHouse使用的Demo
-https://github.com/chenyanlann/APIJSONDemo_ClickHouse - -#### zhaoqiming 1.完善入门介绍视频 -APIJSON 后端教程(1):简介 -https://www.bilibili.com/video/BV1vL411W7yd - -APIJSON 后端教程(2):数据库 -https://www.bilibili.com/video/BV1eB4y1N77s - -APIJSON 后端教程(3):Demo -https://www.bilibili.com/video/BV1FX4y1c7ug - -APIJSON 后端教程(4):Boot -https://www.bilibili.com/video/BV18h411z7FK - -APIJSON 后端教程(5):Final -https://www.bilibili.com/video/BV1GM4y1N7XJ - -APIJSON 后端教程(6):uliweb_apijson -https://www.bilibili.com/video/BV1yb4y1S79v/ - -APIJSON 后端教程(7):问题答疑 -https://www.bilibili.com/video/BV1dQ4y1h7Df - -APIJSON配套文档: -https://github.com/kenlig/apijsondocs - -#### huwen 2.接入 presto/hive/clickhouse/db2 任意一个 -APIJSON-Demo 接入presto -https://github.com/hclown9804/APIJSONDemo_presto - -#### zhanghaoling 1.完善入门介绍视频 -APIJSON结合已有项目,简化开发流程 -https://github.com/haolingzhang1/APIJson--demo - -说明文档 -https://github.com/haolingzhang1/APIJson--demo/tree/main/APIJson集成项目说明 - -(1)官方demo -https://github.com/haolingzhang1/APIJson--demo/blob/main/APIJson集成项目说明/APIJson集成现有项目(1)-%20官方demo.pdf - -(2)单表配置 -https://github.com/haolingzhang1/APIJson--demo/blob/main/APIJson集成项目说明/APIJson集成现有项目(2)-%20单表配置.pdf - -#### zhoukaile 1.完善入门介绍视频 - -视频链接:https://www.bilibili.com/video/BV1Uh411z7kZ/ - -文档链接:https://gitee.com/funkiz/apijson_camp - -#### lintao 1.完善入门介绍视频 - -APIJSON 上手教程:https://www.bilibili.com/video/BV1Pq4y1n7rJ - -### 持续更新 - -https://github.com/Tencent/APIJSON/commits/master - -### 工蜂主页 -https://git.code.tencent.com/Tencent_Open_Source/APIJSON - -### 码云主页 -https://gitee.com/Tencent/APIJSON +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_user_role", + "Sys_user_role": { + "@column": "role_id", + "user_id": "4732209c-5785-4827-b532-5092f154fd94" + } + }, + "Sys_role": { + "@method": "heads", + "id{}@": "sql" + }, + "@explain": true +} + +``` + +mysql8执行sql语句: + +![img](https://tcs-devops.aliyuncs.com/storage/112offc8ee52b3bd03af5012ae9832ed7800?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9mZmM4ZWU1MmIzYmQwM2FmNTAxMmFlOTgzMmVkNzgwMCJ9.aPpEd5GM5iTIs149Xc2kxovMu82HzbZUHd3L7yrtkQE) + +mysql5.7执行结果: + +![img](https://tcs-devops.aliyuncs.com/storage/112o1ad0c28563c50c245ee39d399fcbf817?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0OTE3MywiaWF0IjoxNjY5MzQ0MzczLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8xYWQwYzI4NTYzYzUwYzI0NWVlMzlkMzk5ZmNiZjgxNyJ9.Wc4X-gAhJhKtFDIc15i8Y-JFb6BYy4EBVGNQ0fq2_SE) + +#### heads 多个子查询 + +Access、Request需要配置鉴权信息: + +![img](https://tcs-devops.aliyuncs.com/storage/112od6c06bedd0338403de83a3da034862b6?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9kNmMwNmJlZGQwMzM4NDAzZGU4M2EzZGEwMzQ4NjJiNiJ9.c4OVSUGncl_anepEZN1jzHmk7FiIRY-UcRj6EOn0ySk) + +普通获取数量 + +``` +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_role", + "Sys_role": { + "@column": "id", + "role_name": "超级管理员" + } + }, + "sql_user@": { + "@method": "GET", + "with": true, + "from": "Sys_user", + "Sys_user": { + "@column": "id", + "id": "4732209c-5785-4827-b532-5092f154fd94" + } + }, + "Sys_user_role": { + "@method": "HEADS", + "role_id{}@": "sql", + "user_id{}@": "sql_user" + }, + "Sys_role_permission": { + "@method": "HEADS", + "role_id{}@": "sql" + }, + "@explain": true +} + +``` + +mysql8执行sql语句: + +![img](https://tcs-devops.aliyuncs.com/storage/112oa28b0fce57d06fea1386164f4183f4df?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9hMjhiMGZjZTU3ZDA2ZmVhMTM4NjE2NGY0MTgzZjRkZiJ9.7UtbXd2E6tU6aSicO_LoEhQfPvViN2SCrF2-UdhkHyk) + +mysql5.7执行结果: + +![img](https://tcs-devops.aliyuncs.com/storage/112od2bd40102e4250e79caeae832dcacd77?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0OTIzMywiaWF0IjoxNjY5MzQ0NDMzLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9kMmJkNDAxMDJlNDI1MGU3OWNhZWFlODMyZGNhY2Q3NyJ9.0mgwZshZSKSxxkak2mJfj8LHrIyjVj2NTKghOVJ0-J0) + + + +### delete 支持子查询 + +https://github.com/Tencent/APIJSON/issues/471 + +静态变量做全局处理,特殊接口用 Operation.MUST id/id{}/id{}@ 做自定义处理。 + +之所以默认必传,是因为安全意识不够、编码粗心大意的人太多了,所以要有一个底线保障,尽可能避免安全隐患。 + +1、全局配置 为 PUT, DELETE 强制要求必须有 id/id{}/id{}@ 条件 + +AbstractVerifier.IS_UPDATE_MUST_HAVE_ID_CONDITION = true; // true: 必须有 + +2、细粒度控制 + +![image-20221125154603033](/Users/xy/Library/Application Support/typora-user-images/image-20221125154603033.png) + +#### 使用说明 + +``` +// 条件删除 +{ + "User:del": { + "username": "test3" + }, + "tag": "User", + "explain": true +} + +// 引用id{}@删除 +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_user_role", + "Sys_user_role": { + "@column": "user_id", + "role_id{}": ["023e1880-c0d4-4e7c-ae6c-7703199c2daf"] + } + }, + "Sys_user:aa": { + "@method": "DELETE", + "id{}@": "sql" + }, + "explan": true +} +// 子查询条件删除 +http://localhost:8675/lowCodePlatform/forms/api/delete +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "User", + "User": { + "@column": "username", + "username": "test-3" + } + }, + "User": { + "username{}@": "sql" + }, + "explan": true +} + +第二种写法: +{ + "@get": ["sql@"], + "sql@": { + "with": true, + "from": "User", + "User": { + "@column": "username", + "username": "test4" + } + }, + "User": { + "username{}@": "sql" + }, + "explan": true +} + + +``` + + + +开启id删除, 删除失败: + +``` +{ + "@get": ["sql@"], + "sql@": { + "with": true, + "from": "User", + "User": { + "@column": "username", + "username": "test4" + } + }, + "User": { + "username{}@": "sql" + }, + "explan": true +} +``` + +![image-20221125161720199](/Users/xy/Library/Application Support/typora-user-images/image-20221125161720199.png) + +#### bug修复 + +删除操作 主表 和 子查询 是同一张表 +mysql8以下 非with-as表达式 会报错: +"msg": "You can't specify target table 'User' for update in FROM clause", + +需要调整sql语句,将子查询包一层(select * from (子查询) as xxx) +DELETE FROM `housekeeping`.`User` +WHERE ( (`username` IN (SELECT * FROM (SELECT `username` FROM `housekeeping`.`User` WHERE ( (`username` = 'test1') )) as a) ) ) + +![image](https://user-images.githubusercontent.com/12228225/203517122-3d5b3b90-9780-4e05-b633-b264c575757a.png) + +![image](https://user-images.githubusercontent.com/12228225/203517315-4ab11545-4285-4737-92a3-cfd1494e2652.png) + +### must判断、delete删除支持 ref + +``` +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_role_permission", + "Sys_role_permission": { + "@column": "id", + "role_id{}": ["94f79f0b-331b-4cc5-bfc0-ebfc47d00f13"] + } + }, + "Sys_role_permission": { + "@method": "DELETE", + "id{}@": "sql" + }, + "explan": true +} +``` + +![image-20221125161821101](/Users/xy/Library/Application Support/typora-user-images/image-20221125161821101.png) From b908fd010f46349420a60401714e4a2b7f8f4bfa Mon Sep 17 00:00:00 2001 From: cloudAndMonkey Date: Sat, 26 Nov 2022 15:59:24 +0800 Subject: [PATCH 2/5] Add files via upload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、一个json(事务)同时支持新增、修改、删除、查询、别名 2、delete、put 支持子查询 3、mysql8 with-as表达式 4、bug修复 删除操作 主表 和 子查询 是同一张表 mysql8以下 非with-as表达式 会报错: "msg": "You can't specify target table 'User' for update in FROM clause", 5、must、refuses判断、delete、put支持 ref --- .../src/main/java/apijson/JSONObject.java | 1 + .../src/main/java/apijson/StringUtil.java | 2 +- .../main/java/apijson/orm/AbstractParser.java | 191 +++++++++++++++--- .../java/apijson/orm/AbstractSQLConfig.java | 90 ++++++++- .../java/apijson/orm/AbstractSQLExecutor.java | 9 + .../java/apijson/orm/AbstractVerifier.java | 19 +- .../src/main/java/apijson/orm/SQLConfig.java | 2 + 7 files changed, 280 insertions(+), 34 deletions(-) diff --git a/APIJSONORM/src/main/java/apijson/JSONObject.java b/APIJSONORM/src/main/java/apijson/JSONObject.java index 6825a02de..db21693cf 100755 --- a/APIJSONORM/src/main/java/apijson/JSONObject.java +++ b/APIJSONORM/src/main/java/apijson/JSONObject.java @@ -151,6 +151,7 @@ public JSONObject setUserIdIn(List list) { public static final String KEY_ORDER = "@order"; //排序方式 public static final String KEY_RAW = "@raw"; // 自定义原始 SQL 片段 public static final String KEY_JSON = "@json"; //SQL Server 把字段转为 JSON 输出 + public static final String KEY_METHOD = "@method"; //json对象配置操作方法 public static final List TABLE_KEY_LIST; static { diff --git a/APIJSONORM/src/main/java/apijson/StringUtil.java b/APIJSONORM/src/main/java/apijson/StringUtil.java index 795392e49..67ca446f6 100755 --- a/APIJSONORM/src/main/java/apijson/StringUtil.java +++ b/APIJSONORM/src/main/java/apijson/StringUtil.java @@ -354,7 +354,7 @@ public static boolean isNotEmpty(String s, boolean trim) { PATTERN_ALPHA = Pattern.compile("^[a-zA-Z]+$"); PATTERN_ALPHA_BIG = Pattern.compile("^[A-Z]+$"); PATTERN_ALPHA_SMALL = Pattern.compile("^[a-z]+$"); - PATTERN_NAME = Pattern.compile("^[0-9a-zA-Z_]+$");//已用55个中英字符测试通过 + PATTERN_NAME = Pattern.compile("^[0-9a-zA-Z_:]+$");//已用55个中英字符测试通过 //newest phone regex expression reference https://github.com/VincentSit/ChinaMobilePhoneNumberRegex PATTERN_PHONE = Pattern.compile("^1(?:3\\d{3}|5[^4\\D]\\d{2}|8\\d{3}|7(?:[0-35-9]\\d{2}|4(?:0\\d|1[0-2]|9\\d))|9[0-35-9]\\d{2}|6[2567]\\d{2}|4(?:(?:10|4[01])\\d{3}|[68]\\d{4}|[579]\\d{2}))\\d{6}$"); PATTERN_EMAIL = Pattern.compile("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$"); diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java index e99908024..6c8195bf2 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java @@ -47,7 +47,7 @@ */ public abstract class AbstractParser implements Parser, ParserCreator, VerifierCreator, SQLCreator { protected static final String TAG = "AbstractParser"; - + protected Map key_method_Map = new HashMap<>(); /** * 可以通过切换该变量来控制是否打印关键的接口请求内容。保守起见,该值默认为false。 * 与 {@link Log#DEBUG} 任何一个为 true 都会打印关键的接口请求内容。 @@ -572,28 +572,11 @@ public JSONObject parseCorrectRequest(RequestMethod method, String tag, int vers return request;//需要指定JSON结构的get请求可以改为post请求。一般只有对安全性要求高的才会指定,而这种情况用明文的GET方式几乎肯定不安全 } - if (StringUtil.isEmpty(tag, true)) { - throw new IllegalArgumentException("请在最外层传 tag !一般是 Table 名,例如 \"tag\": \"User\" "); - } - - //获取指定的JSON结构 <<<<<<<<<<<< - JSONObject object = null; - String error = ""; - try { - object = getStructure("Request", method.name(), tag, version); - } catch (Exception e) { - error = e.getMessage(); - } - if (object == null) { //empty表示随意操作 || object.isEmpty()) { - throw new UnsupportedOperationException("找不到 version: " + version + ", method: " + method.name() + ", tag: " + tag + " 对应的 structure !" - + "非开放请求必须是后端 Request 表中校验规则允许的操作!\n " + error + "\n如果需要则在 Request 表中新增配置!"); - } - - //获取指定的JSON结构 >>>>>>>>>>>>>> - JSONObject target = wrapRequest(method, tag, object, true); +// if (StringUtil.isEmpty(tag, true)) { +// throw new IllegalArgumentException("请在最外层传 tag !一般是 Table 名,例如 \"tag\": \"User\" "); +// } - //JSONObject clone 浅拷贝没用,Structure.parse 会导致 structure 里面被清空,第二次从缓存里取到的就是 {} - return getVerifier().verifyRequest(method, name, target, request, maxUpdateCount, getGlobalDatabase(), getGlobalSchema(), creator); + return batchVerify(method, tag, version, name, request, maxUpdateCount, creator); } @@ -1047,6 +1030,8 @@ public JSONObject onObjectParse(final JSONObject request if (op == null) { op = createObjectParser(request, parentPath, arrayConfig, isSubquery, isTable, isArrayMainTable); } + // 对象 - 设置 method + setOpMethod(request, op, name); op = op.parse(name, isReuse); JSONObject response = null; @@ -2022,7 +2007,8 @@ protected void onBegin() { */ protected void onCommit() { // Log.d(TAG, "onCommit >>"); - if (RequestMethod.isQueryMethod(requestMethod)) { + // this.sqlExecutor.getTransactionIsolation() 只有json第一次执行才会设置, get请求=0 + if (RequestMethod.isQueryMethod(requestMethod) && this.sqlExecutor.getTransactionIsolation() == Connection.TRANSACTION_NONE ) { return; } @@ -2068,4 +2054,163 @@ protected void onClose() { queryResultMap = null; } + private void setOpMethod(JSONObject request,ObjectParser op, String key) { + if(key != null && request.getString(apijson.JSONObject.KEY_METHOD) != null) { + String _method = request.getString(apijson.JSONObject.KEY_METHOD); + if( _method != null) { + RequestMethod method = RequestMethod.valueOf(_method.toUpperCase()); + this.setMethod(method); + op.setMethod(method); + } + } + } + + protected JSONObject getRequestStructure(RequestMethod method, String tag, int version) throws Exception { + // 获取指定的JSON结构 <<<<<<<<<<<< + JSONObject object = null; + String error = ""; + try { + object = getStructure("Request", method.name(), tag, version); + } catch (Exception e) { + error = e.getMessage(); + } + if (object == null) { // empty表示随意操作 || object.isEmpty()) { + throw new UnsupportedOperationException("找不到 version: " + version + ", method: " + method.name() + ", tag: " + tag + " 对应的 structure !" + "非开放请求必须是后端 Request 表中校验规则允许的操作!\n " + error + "\n如果需要则在 Request 表中新增配置!"); + } + return object; + } + + private JSONObject batchVerify(RequestMethod method, String tag, int version, String name, @NotNull JSONObject request, int maxUpdateCount, SQLCreator creator) throws Exception { + JSONObject jsonObject = new JSONObject(true); + if (request.keySet() == null || request.keySet().size() == 0) { + throw new IllegalArgumentException("json对象格式不正确 !,例如 \"User\": {}"); + } + + for (String key : request.keySet()) { + // key重复直接抛错(xxx:alias, xxx:alias[]) + if (jsonObject.containsKey(key) || jsonObject.containsKey(key + apijson.JSONObject.KEY_ARRAY)) { + throw new IllegalArgumentException("对象名重复,请添加别名区分 ! ,重复对象名为: " + key); + } + + // @post、@get等RequestMethod + try { + if (key.startsWith("@")) { + try { + // 如果不匹配,不处理即可 + RequestMethod l_method = RequestMethod.valueOf(key.substring(1).toUpperCase()); + if (l_method != null) { + if (request.get(key) instanceof JSONArray) { + for (Object objKey : request.getJSONArray(key)) { + key_method_Map.put(objKey, l_method); + } + continue; + } else { + throw new IllegalArgumentException("参数 " + key + " 必须是数组格式 ! ,例如: [\"Moment\", \"Comment[]\"]"); + } + } + } catch (Exception e) { + } + } + + // 如果对象设置了@method, 优先使用 对象内部的@method + // 对于没有显式声明操作方法的,直接用 URL(/get, /post 等) 对应的默认操作方法 + // 将method 设置到每个object, op执行会解析 + if (request.get(key) instanceof JSONObject) { + if(request.getJSONObject(key).getString(apijson.JSONObject.KEY_METHOD) == null) { + if (key_method_Map.get(key) == null) { + // 数组会解析为对象进行校验,做一下兼容 + if(key_method_Map.get(key + apijson.JSONObject.KEY_ARRAY) == null) { + request.getJSONObject(key).put(apijson.JSONObject.KEY_METHOD, method); + }else { + request.getJSONObject(key).put(apijson.JSONObject.KEY_METHOD, key_method_Map.get(key + apijson.JSONObject.KEY_ARRAY)); + } + } else { + request.getJSONObject(key).put(apijson.JSONObject.KEY_METHOD, key_method_Map.get(key)); + } + } + + // get请求不校验 + RequestMethod _method = RequestMethod.valueOf(request.getJSONObject(key).getString(apijson.JSONObject.KEY_METHOD).toUpperCase()); + if (RequestMethod.isPublicMethod(_method)) { + jsonObject.put(key, request.getJSONObject(key)); + continue; + } + } + + if (key.startsWith("@") || key.endsWith("@")) { + jsonObject.put(key, request.get(key)); + continue; + } + + + if (request.get(key) instanceof JSONObject || request.get(key) instanceof JSONArray) { + RequestMethod _method = null; + if (request.get(key) instanceof JSONObject) { + _method = RequestMethod.valueOf(request.getJSONObject(key).getString(apijson.JSONObject.KEY_METHOD).toUpperCase()); + } else { + if (key_method_Map.get(key) == null) { + _method = method; + } else { + _method = key_method_Map.get(key); + } + } + + String _tag = buildTag(request, key); + JSONObject requestItem = new JSONObject(); + requestItem.put(_tag, request.get(key)); + JSONObject object = getRequestStructure(_method, _tag, version); + JSONObject ret = objectVerify(_method, _tag, version, name, requestItem, maxUpdateCount, creator, object); + jsonObject.put(key, ret.get(_tag)); + } else { + jsonObject.put(key, request.get(key)); + } + } catch (Exception e) { + e.printStackTrace(); + throw new Exception(e); + } + } + + return jsonObject; + } + + /** + * { "xxx:aa":{ "@tag": "" }, "tag": "User" } + * 1、@tag存在,tag=@tag + * 2、@tag不存在 + * 生成规则: + * 1、存在别名 + * key=对象: tag=key去除别名 + * key=数组: tag=key去除别名 + [] + * 2、不存在别名 + * tag=key + * tag=key + [] + * @param request + * @param key + * @return + */ + private String buildTag(JSONObject request, String key) { + String _tag = null; + if (request.get(key) instanceof JSONObject && request.getJSONObject(key).getString("@tag") != null) { + _tag = request.getJSONObject(key).getString("@tag"); + } else { + int keyIndex = key.indexOf(":"); + if (keyIndex != -1) { + _tag = key.substring(0, keyIndex); + if (apijson.JSONObject.isTableArray(key)) { + _tag += apijson.JSONObject.KEY_ARRAY; + } + } else { + // 不存在别名 + _tag = key; + } + } + return _tag; + } + + protected JSONObject objectVerify(RequestMethod method, String tag, int version, String name, @NotNull JSONObject request, int maxUpdateCount, SQLCreator creator, JSONObject object) throws Exception { + // 获取指定的JSON结构 >>>>>>>>>>>>>> + JSONObject target = wrapRequest(method, tag, object, true); + // JSONObject clone 浅拷贝没用,Structure.parse 会导致 structure 里面被清空,第二次从缓存里取到的就是 {} + return getVerifier().verifyRequest(method, name, target, request, maxUpdateCount, getGlobalDatabase(), getGlobalSchema(), creator); + } } diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java index 6e10ce2ca..21cb36071 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java @@ -761,6 +761,9 @@ public abstract class AbstractSQLConfig implements SQLConfig { } + // mysql8版本以上,子查询支持with as表达式 + private List withAsExpreSqlList = null; + protected List withAsExprePreparedValueList = new ArrayList<>(); private int[] dbVersionNums = null; @Override public int[] getDBVersionNums() { @@ -3909,6 +3912,39 @@ else if (isPresto() || isTrino()) { //key@:{} Subquery <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + /** + * 只要 method != RequestMethod.POST 就都支持 with-as表达式 + * @param cfg + * @param subquery + * @return + * @throws Exception + */ + private String withAsExpreSubqueryString(SQLConfig cfg, Subquery subquery) throws Exception { + if(cfg.getMethod() != RequestMethod.POST && this.withAsExpreSqlList == null) { + this.setWithAsExpreList(); + } + String withAsExpreSql; + if(this.withAsExpreSqlList != null) { + String withQuoteName = getQuote() + subquery.getKey() + getQuote(); + this.withAsExpreSqlList.add(" " + withQuoteName + " AS " + "(" + cfg.getSQL(isPrepared()) + ") "); + withAsExpreSql = " SELECT * FROM " + withQuoteName; + + // 预编译参数 + List subPvl = cfg.getPreparedValueList(); + if (subPvl != null && subPvl.isEmpty() == false) { + this.withAsExprePreparedValueList.addAll(subPvl); + cfg.setPreparedValueList(new ArrayList<>()); + } + }else { + withAsExpreSql = cfg.getSQL(isPrepared()); + // mysql 才存在这个问题, 主表和子表是一张表 + if(this.isMySQL() && StringUtil.equals(this.getTable(), subquery.getFrom())) { + withAsExpreSql = " SELECT * FROM (" + withAsExpreSql+") AS " + getQuote() + subquery.getKey() + getQuote(); + } + } + return withAsExpreSql; + } + @Override public String getSubqueryString(Subquery subquery) throws Exception { if (subquery == null) { @@ -3919,7 +3955,8 @@ public String getSubqueryString(Subquery subquery) throws Exception { SQLConfig cfg = subquery.getConfig(); cfg.setPreparedValueList(new ArrayList<>()); - String sql = (range == null || range.isEmpty() ? "" : range) + "(" + cfg.getSQL(isPrepared()) + ") "; + String withAsExpreSql = withAsExpreSubqueryString(cfg, subquery); + String sql = (range == null || range.isEmpty() ? "" : range) + "(" + withAsExpreSql + ") "; //// SELECT .. FROM(SELECT ..) .. WHERE .. 格式需要把子查询中的预编译值提前 //// 如果外查询 SELECT concat(`name`,?) 这种 SELECT 里也有预编译值,那就不能这样简单反向 @@ -4123,6 +4160,7 @@ public static String getSQL(AbstractSQLConfig config) throws Exception { return null; } + String cSql = null; switch (config.getMethod()) { case POST: return "INSERT INTO " + tablePath + config.getColumnString() + " VALUES" + config.getValuesString(); @@ -4130,12 +4168,16 @@ public static String getSQL(AbstractSQLConfig config) throws Exception { if(config.isClickHouse()){ return "ALTER TABLE " + tablePath + " UPDATE" + config.getSetString() + config.getWhereString(true); } - return "UPDATE " + tablePath + config.getSetString() + config.getWhereString(true) + (config.isMySQL() ? config.getLimitString() : ""); + cSql = "UPDATE " + tablePath + config.getSetString() + config.getWhereString(true) + (config.isMySQL() ? config.getLimitString() : ""); + cSql = buildWithAsExpreSql(config, cSql); + return cSql; case DELETE: if(config.isClickHouse()){ return "ALTER TABLE " + tablePath + " DELETE" + config.getWhereString(true); } - return "DELETE FROM " + tablePath + config.getWhereString(true) + (config.isMySQL() ? config.getLimitString() : ""); // PostgreSQL 不允许 LIMIT + cSql = "DELETE FROM " + tablePath + config.getWhereString(true) + (config.isMySQL() ? config.getLimitString() : ""); // PostgreSQL 不允许 LIMIT + cSql = buildWithAsExpreSql(config, cSql); + return cSql; default: String explain = config.isExplain() ? (config.isSQLServer() ? "SET STATISTICS PROFILE ON " : (config.isOracle() || config.isDameng() || config.isKingBase() ? "EXPLAIN PLAN FOR " : "EXPLAIN ")) : ""; if (config.isTest() && RequestMethod.isGetMethod(config.getMethod(), true)) { // FIXME 为啥是 code 而不是 count ? @@ -4156,8 +4198,32 @@ public static String getSQL(AbstractSQLConfig config) throws Exception { return explain + config.getOraclePageSql(sql); } - return explain + "SELECT " + (config.getCache() == JSONRequest.CACHE_RAM ? "SQL_NO_CACHE " : "") + column + " FROM " + getConditionString(tablePath, config) + config.getLimitString(); + cSql = "SELECT " + (config.getCache() == JSONRequest.CACHE_RAM ? "SQL_NO_CACHE " : "") + column + " FROM " + getConditionString(tablePath, config) + config.getLimitString(); + cSql = buildWithAsExpreSql(config, cSql); + return explain + cSql; + } + } + + private static String buildWithAsExpreSql(@NotNull AbstractSQLConfig config, String cSql) throws Exception { + if(config.withAsExpreSqlList != null && config.withAsExpreSqlList.size() > 0) { + String withAsExpreSql = "WITH "; + // 只有一条 + if(config.withAsExpreSqlList.size() == 1) { + withAsExpreSql += config.withAsExpreSqlList.get(0) + "\n" + cSql; + }else { + int lastIndex = config.withAsExpreSqlList.size() - 1; + for (int i = 0; i < config.withAsExpreSqlList.size(); i++) { + if(i == lastIndex) { + withAsExpreSql += config.withAsExpreSqlList.get(i) + "\n" + cSql; + }else { + withAsExpreSql += config.withAsExpreSqlList.get(i) + ",\n"; + } + } + } + cSql = withAsExpreSql; + config.setWithAsExpreList(); } + return cSql; } /**Oracle的分页获取 @@ -5508,4 +5574,20 @@ public void onMissingKey4Combine(String name, JSONObject request, String combine } + private void setWithAsExpreList() { + // mysql8版本以上,子查询支持with as表达式 + if(this.isMySQL() && this.getDBVersionNums()[0] >= 8) { + this.withAsExpreSqlList = new ArrayList<>(); + } + } + + @Override + public List getWithAsExprePreparedValueList() { + return this.withAsExprePreparedValueList; + } + + @Override + public void setWithAsExprePreparedValueList(List list) { + this.withAsExprePreparedValueList = list; + } } diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java index a9b023d3a..9bbd76d71 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java @@ -1101,6 +1101,15 @@ else if (RequestMethod.isGetMethod(config.getMethod(), true)) { } List valueList = config.isPrepared() ? config.getPreparedValueList() : null; + List withAsExprePreparedValueList = config.isPrepared() ? config.getWithAsExprePreparedValueList() : null; + + // 不同数据库, 预编译mysql使用with-as + if (valueList != null && withAsExprePreparedValueList != null && withAsExprePreparedValueList.size() > 0) { + withAsExprePreparedValueList.addAll(valueList); + valueList = withAsExprePreparedValueList; + // 多条POST/PUT/DELETE语句的情况,需要重新初始化 + config.setWithAsExprePreparedValueList(new ArrayList<>()); + } if (valueList != null && valueList.isEmpty() == false) { for (int i = 0; i < valueList.size(); i++) { diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java index 3b4422bae..334143493 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java @@ -81,6 +81,9 @@ public abstract class AbstractVerifier implements Verifier, IdCallback { private static final String TAG = "AbstractVerifier"; + /**为 PUT, DELETE 强制要求必须有 id/id{} 条件 + */ + public static boolean IS_UPDATE_MUST_HAVE_ID_CONDITION = true; /**开启校验请求角色权限 */ public static boolean ENABLE_VERIFY_ROLE = true; @@ -673,7 +676,7 @@ public JSONObject onParseJSONObject(String key, JSONObject tobj, JSONObject robj } } else { if (RequestMethod.isQueryMethod(method) == false) { - verifyId(method.name(), name, key, robj, finalIdKey, maxUpdateCount, true); + verifyId(method.name(), name, key, robj, finalIdKey, maxUpdateCount, IS_UPDATE_MUST_HAVE_ID_CONDITION); String userIdKey = idCallback == null ? null : idCallback.getUserIdKey(db, sh, ds, key); String finalUserIdKey = StringUtil.isEmpty(userIdKey, false) ? apijson.JSONObject.KEY_USER_ID : userIdKey; @@ -724,7 +727,8 @@ private static void verifyId(@NotNull String method, @NotNull String name, @NotN //批量修改或删除 String idInKey = idKey + "{}"; - + // id引用, 格式: "id{}@": "sql" + String idRefInKey = robj.getString(idKey + "{}@"); JSONArray idIn = null; try { idIn = robj.getJSONArray(idInKey); //如果必须传 id{} ,可在Request表中配置NECESSARY @@ -733,9 +737,9 @@ private static void verifyId(@NotNull String method, @NotNull String name, @NotN + " 里面的 " + idInKey + ":value 中value的类型只能是 [Long] !"); } if (idIn == null) { - if (atLeastOne && id == null) { + if (atLeastOne && id == null && idRefInKey == null) { throw new IllegalArgumentException(method + "请求," + name + "/" + key - + " 里面 " + idKey + " 和 " + idInKey + " 至少传其中一个!"); + + " 里面 " + idKey + "," + idInKey + "," + (idKey + "{}@") + " 至少传其中一个!"); } } else { if (idIn.size() > maxUpdateCount) { //不允许一次操作 maxUpdateCount 条以上记录 @@ -922,7 +926,7 @@ public static JSONObject parse(@NotNull final RequestMethod m if (musts != null && musts.length > 0) { for (String s : musts) { - if (real.get(s) == null) { // 可能传null进来,这里还会通过 real.containsKey(s) == false) { + if (real.get(s) == null && real.get(s+"@") == null) { // 可能传null进来,这里还会通过 real.containsKey(s) == false) { throw new IllegalArgumentException(method + "请求," + name + " 里面不能缺少 " + s + " 等[" + must + "]内的任何字段!"); } @@ -1018,7 +1022,10 @@ public static JSONObject parse(@NotNull final RequestMethod m || mustSet.contains(key) || objKeySet.contains(key)) { continue; } - + // 支持id ref: id{}@ + if (key.endsWith("@") && mustSet.contains(key.substring(0, key.length() - 1))) { + continue; + } refuseSet.add(key); } } diff --git a/APIJSONORM/src/main/java/apijson/orm/SQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/SQLConfig.java index 83f488b85..1a0f5e97b 100755 --- a/APIJSONORM/src/main/java/apijson/orm/SQLConfig.java +++ b/APIJSONORM/src/main/java/apijson/orm/SQLConfig.java @@ -307,4 +307,6 @@ default int[] getDBVersionNums() { + List getWithAsExprePreparedValueList(); + void setWithAsExprePreparedValueList(List withAsExprePreparedValueList); } From 672b8ba828504bbe22b98de9ade5bed90bbedab5 Mon Sep 17 00:00:00 2001 From: cloudAndMonkey Date: Sat, 26 Nov 2022 16:08:11 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 110 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 9e7409bdb..15404c65a 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ delete子查询, druid wall 拦截器报错 sql injection violation #### 测试案例 -查询单个range ref引用 +#### 查询单个range ref引用 ``` // 测试 mysql8 with as表达式 @@ -272,12 +272,40 @@ mysql5.7执行结果: #### 查询多个range ref引用 ``` -{ "sql@": { "@method": "GET", "with": true, "from": "Sys_role", "Sys_role": { "@column": "id", "role_name": "角色1" } }, "sql_user@": { "@method": "GET", "with": true, "from": "Sys_user", "Sys_user": { "@column": "id", "id": "f0894db2-6940-4d89-a5b2-4405d0ad0c8f" } }, "Sys_user_role:sur[]": { "@method": "GET", "Sys_user_role": { "role_id{}@": "sql", "user_id{}@": "sql_user" } }, "Sys_role_permission:srp[]": { "@method": "GET", "Sys_role_permission": { "role_id{}@": "sql" } }, "@explain": true} - - - - -Plain Text +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_role", + "Sys_role": { + "@column": "id", + "role_name": "角色1" + } + }, + "sql_user@": { + "@method": "GET", + "with": true, + "from": "Sys_user", + "Sys_user": { + "@column": "id", + "id": "f0894db2-6940-4d89-a5b2-4405d0ad0c8f" + } + }, + "Sys_user_role:sur[]": { + "@method": "GET", + "Sys_user_role": { + "role_id{}@": "sql", + "user_id{}@": "sql_user" + } + }, + "Sys_role_permission:srp[]": { + "@method": "GET", + "Sys_role_permission": { + "role_id{}@": "sql" + } + }, + "@explain": true +} ``` mysql8执行结果: @@ -385,6 +413,8 @@ mysql5.7执行结果: #### GETS 单条子查询 +会执行校验流程 + ``` http://localhost:8675/lowCodePlatform/forms/api/gets @@ -450,6 +480,8 @@ mysql5.7执行结果: #### GETS多条子查询 +会执行校验流程 + ``` http://localhost:8675/lowCodePlatform/forms/api/gets @@ -500,7 +532,7 @@ mysql5.7执行结果: #### head 单个子查询 -普通获取数量 +普通获取数量, get/head不执行校验流程 ``` http://localhost:8675/lowCodePlatform/forms/api/head @@ -533,7 +565,7 @@ mysql5.7执行结果: #### head 多个子查询 -普通获取数量 +普通获取数量, get/head不执行校验流程 ``` { @@ -581,7 +613,7 @@ mysql5.7执行结果: 普通获取数量 -Access、Request需要配置鉴权信息: +会执行校验流程, Access、Request需要配置鉴权信息: ![img](https://tcs-devops.aliyuncs.com/storage/112oe091e1d4376a6fcb62cbce0383cdddf9?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9lMDkxZTFkNDM3NmE2ZmNiNjJjYmNlMDM4M2NkZGRmOSJ9._BSyl8VzN15CTAxr_J1ud0tzYCBQwGQWqaiBRvmau8Q) @@ -617,7 +649,7 @@ mysql5.7执行结果: #### heads 多个子查询 -Access、Request需要配置鉴权信息: +会执行校验流程, Access、Request需要配置鉴权信息: ![img](https://tcs-devops.aliyuncs.com/storage/112od6c06bedd0338403de83a3da034862b6?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9kNmMwNmJlZGQwMzM4NDAzZGU4M2EzZGEwMzQ4NjJiNiJ9.c4OVSUGncl_anepEZN1jzHmk7FiIRY-UcRj6EOn0ySk) @@ -667,7 +699,7 @@ mysql5.7执行结果: -### delete 支持子查询 +### delete、put 支持子查询 https://github.com/Tencent/APIJSON/issues/471 @@ -679,6 +711,8 @@ https://github.com/Tencent/APIJSON/issues/471 AbstractVerifier.IS_UPDATE_MUST_HAVE_ID_CONDITION = true; // true: 必须有 +![image-20221126145415115](/Users/xy/Library/Application Support/typora-user-images/image-20221126145415115.png) + 2、细粒度控制 ![image-20221125154603033](/Users/xy/Library/Application Support/typora-user-images/image-20221125154603033.png) @@ -774,6 +808,54 @@ http://localhost:8675/lowCodePlatform/forms/api/delete ![image-20221125161720199](/Users/xy/Library/Application Support/typora-user-images/image-20221125161720199.png) +开启id删除、id引用 删除成功 + +``` +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_user_role", + "Sys_user_role": { + "@column": "user_id", + "role_id{}": ["0bb92d96-8ca6-469e-91e8-60308ce5b835"] + } + }, + "Sys_user:aa": { + "@method": "DELETE", + "id{}@": "sql" + }, + "explan": true +} +``` + +![image-20221126145714808](/Users/xy/Library/Application Support/typora-user-images/image-20221126145714808.png) + +PUT 子查询 修改 + +``` +{ + "sql@": { + "@method": "GET", + "with": true, + "from": "Sys_role_permission", + "Sys_role_permission": { + "@column": "role_id", + "id{}": ["ba2634f8-0bdc-4b50-9c5e-47786b1536ef"] + } + }, + "Sys_role": { + "@method": "PUT", + "id{}@": "sql", + "role_code": "code-subrange-5", + "role_name": "角色-subrange-5" + }, + "@explain": true +} +``` + +![image-20221126151726450](/Users/xy/Library/Application Support/typora-user-images/image-20221126151726450.png) + #### bug修复 删除操作 主表 和 子查询 是同一张表 @@ -788,7 +870,7 @@ WHERE ( (`username` IN (SELECT * FROM (SELECT `username` FROM `housekeeping`.`Us ![image](https://user-images.githubusercontent.com/12228225/203517315-4ab11545-4285-4737-92a3-cfd1494e2652.png) -### must判断、delete删除支持 ref +### must、refuses判断、delete、PUT支持 ref ``` { @@ -809,4 +891,4 @@ WHERE ( (`username` IN (SELECT * FROM (SELECT `username` FROM `housekeeping`.`Us } ``` -![image-20221125161821101](/Users/xy/Library/Application Support/typora-user-images/image-20221125161821101.png) +![image-20221125161821101](/Users/xy/Library/Application Support/typora-user-images/image-20221125161821101.png) \ No newline at end of file From 6565b356ce99e72f63bb572cdbd14aa93f2296c9 Mon Sep 17 00:00:00 2001 From: cloudAndMonkey Date: Sat, 26 Nov 2022 16:38:58 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E7=82=B9=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 100 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 15404c65a..09301ddca 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,25 @@ key= Moment[] 2) "@post","@put","@delete" 3) 对于没有显式声明操作方法的,直接用 URL(/get, /post 等) 对应的默认操作方法 +#### tag自动生成规则 + +/** + * { "xxx:aa":{ "@tag": "" }} + * 生成规则: + * 1、@tag存在,tag=@tag + * 2、@tag不存在 + * 1)、存在别名 + * key=对象: tag=key去除别名 + * key=数组: tag=key去除别名 + [] + * 2)、不存在别名 + * tag=key + * tag=key + [] + */ + + +![image](https://user-images.githubusercontent.com/12228225/204079184-06dd08a7-95a3-4a46-8e05-f062fa406847.png) + + #### 建议 1. 一个json包含不同操作方法, url method 使用 /post, /put @@ -105,8 +124,9 @@ PUT User_address[] {"User_address[]": [{"MUST": "id","REFUSE": "userId"}], "UPD DELETE User_address {"User_address":{ "MUST":"id{}","REFUSE": "!", "INSERT": {"@role": "OWNER,ADMIN"}} } ``` +![image](https://user-images.githubusercontent.com/12228225/204079438-8f352496-4b73-4b72-88c0-914894335074.png) + -![img](https://tcs-devops.aliyuncs.com/storage/112o42fb67f3226bf1ba31143f8e3983d0d3?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk2MjcxMiwiaWF0IjoxNjY5MzU3OTEyLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm80MmZiNjdmMzIyNmJmMWJhMzExNDNmOGUzOTgzZDBkMyJ9.c0kLsYpkpHzkVchL8ZxzUiPf0uvD3G-dsrIc1_zxBl0) ### 别名 @@ -118,7 +138,7 @@ Comment:cArray[] #### 实现思路 -当时参考了作者的示例: 注册流程. 看到绕过校验, 可以将多条json语句组装在一起, 批量执行. 于是就想如何实现一个json支持不同操作,并支持事物. +当时参考了作者的示例: 注册流程. 看到绕过校验, 可以将多条json语句组装在一起, 批量执行. 于是就想如何实现一个json支持不同操作方法,并支持事物. 通过分析源码, 熟悉了校验流程、json解析执行流程、json解析生成sql语句流程、一些兼容、校验规则等 @@ -157,7 +177,7 @@ Comment:cArray[] 2、最外层新增传参 "transaction": true 来指定开启事务 目前是url put、post来控制开启事物, 以及提交的时候 在 AbstractParser onCommit 判断 transactionIsolation (4 : 开启事物, 0: 非事物请求) -![image](https://user-images.githubusercontent.com/12228225/202369747-396a4062-c70d-407e-abfa-c333d4c89bee.png) +![image](https://user-images.githubusercontent.com/12228225/204079532-26d9cd4b-d2d7-4c73-9f78-f425bbbcf623.png) 详细实现请参见: https://github.com/Tencent/APIJSON/issues/468 @@ -165,7 +185,7 @@ Comment:cArray[] 如果没有执行计划,则返回sql语句. 能够在 reponse返回值中, 看到json中执行的每条sql,方便排错 -![img](https://tcs-devops.aliyuncs.com/storage/112oc4589a6d650755c05381097fe9f2294f?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9jNDU4OWE2ZDY1MDc1NWMwNTM4MTA5N2ZlOWYyMjk0ZiJ9.WySq2UEIS5fMySWRqtKiaXzR4wwtQVxrtbSp98vHmx4) +![image](https://user-images.githubusercontent.com/12228225/204079543-be464f67-a80f-4a33-87ea-d1870908e642.png) 4、@version支持 @@ -173,7 +193,7 @@ Comment:cArray[] Request表是通过tag、method、version来保证唯一. -![image-20221125144359453](/Users/xy/Library/Application Support/typora-user-images/image-20221125144359453.png) +![image](https://user-images.githubusercontent.com/12228225/204079562-00449c38-42b1-4d9c-b562-2d56c77e6218.png) 5、前置函数 @@ -199,7 +219,7 @@ Request表是通过tag、method、version来保证唯一. delete子查询, druid wall 拦截器报错 sql injection violation -![image-20221125152519359](/Users/xy/Library/Application Support/typora-user-images/image-20221125152519359.png) +![image](https://user-images.githubusercontent.com/12228225/204079572-19a4f50c-3bf3-4f9e-9677-6aa191276fef.png) #### 测试案例 @@ -263,11 +283,12 @@ delete子查询, druid wall 拦截器报错 sql injection violation mysql8执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112oc4589a6d650755c05381097fe9f2294f?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9jNDU4OWE2ZDY1MDc1NWMwNTM4MTA5N2ZlOWYyMjk0ZiJ9.WySq2UEIS5fMySWRqtKiaXzR4wwtQVxrtbSp98vHmx4) +![image](https://user-images.githubusercontent.com/12228225/204079581-bf835db2-30ae-4265-bda2-ebf34c0d9e77.png) mysql5.7执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112oa2437cfa419471ebdb7ea62dec97ee21?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9hMjQzN2NmYTQxOTQ3MWViZGI3ZWE2MmRlYzk3ZWUyMSJ9.ulNYQKUnvWMIZCpsc-caImZMsF4h21Vq5WdJ03hwjgc) +![image](https://user-images.githubusercontent.com/12228225/204079594-3ebc73a0-836e-4073-9aa4-acb665fe8d52.png) + #### 查询多个range ref引用 @@ -310,11 +331,11 @@ mysql5.7执行结果: mysql8执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112o8c94c21ab8f2f473337a53b369ea8db4?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm84Yzk0YzIxYWI4ZjJmNDczMzM3YTUzYjM2OWVhOGRiNCJ9.DoQZ7uoFEoUonbut23NPp_uzVTZ851PlzZ5FlSZWKGY) +![image](https://user-images.githubusercontent.com/12228225/204079603-2ba224a3-3174-491a-a71b-7656c97d0146.png) mysql5.7执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112o9671ece47b1834ac147cc01cd3900ece?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm85NjcxZWNlNDdiMTgzNGFjMTQ3Y2MwMWNkMzkwMGVjZSJ9.EPqYf1F_RooQF2c5PtrzPdMYCkYZ8Tng4p0Nobgymgc) +![image](https://user-images.githubusercontent.com/12228225/204079611-155f6a33-ad56-4d03-8e5d-6f44c3649051.png) #### delete子查询 @@ -338,7 +359,7 @@ mysql5.7执行结果: ``` -![img](https://tcs-devops.aliyuncs.com/storage/112o12df4490ee563a2a5a36da580823528a?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8xMmRmNDQ5MGVlNTYzYTJhNWEzNmRhNTgwODIzNTI4YSJ9.shAM0ABXqPJTlFYVMU8UjxngUE3jdWgficdNcHgp2Ho) +![image](https://user-images.githubusercontent.com/12228225/204079615-25185be5-a296-488f-9a13-98fb2b99a9d5.png) mysql8执行sql语句: @@ -405,11 +426,12 @@ Plain Text mysql8执行sql语句: -![img](https://tcs-devops.aliyuncs.com/storage/112o69fb17f5eb1c109501063a0501e068ef?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm82OWZiMTdmNWViMWMxMDk1MDEwNjNhMDUwMWUwNjhlZiJ9.1lyjMFAM-y9l5Mu6vlgXRv6S0xRwxoMDdrPTzs8LTbQ) +![image](https://user-images.githubusercontent.com/12228225/204079628-8536b4be-8078-42a5-b3f7-460159372a8a.png) + mysql5.7执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112oe59ad49145a7d0a4f100ba717261ee91?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0ODM1MiwiaWF0IjoxNjY5MzQzNTUyLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9lNTlhZDQ5MTQ1YTdkMGE0ZjEwMGJhNzE3MjYxZWU5MSJ9.bOOaskAmRczI9U87uNNIqB1pQxHlkmeZDzYAd_zmaMI) +![image](https://user-images.githubusercontent.com/12228225/204079633-df9175bc-703f-4997-95f6-85bbc1134b0b.png) #### GETS 单条子查询 @@ -468,15 +490,16 @@ http://localhost:8675/lowCodePlatform/forms/api/gets Access、Request需要配置鉴权信息: -![img](https://tcs-devops.aliyuncs.com/storage/112oc0e2d9666d0e6ae5bba40dd10e86ff8b?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9jMGUyZDk2NjZkMGU2YWU1YmJhNDBkZDEwZTg2ZmY4YiJ9.WiHevTQ80WuelszQxRrsQYWQD4u_60rfj6tsZn9d4vY) +![image](https://user-images.githubusercontent.com/12228225/204079649-510a047b-2b8e-44d2-a32a-f6ea0e7f6a74.png) + mysql8执行sql语句: -![img](https://tcs-devops.aliyuncs.com/storage/112o13624f7ea9b1bbbb31bc4cc83cd96ae6?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8xMzYyNGY3ZWE5YjFiYmJiMzFiYzRjYzgzY2Q5NmFlNiJ9.ZSCMLnTzj7BCi4nxZXSYohKVfHWNR--G5WXv9qE4R1c) +![image](https://user-images.githubusercontent.com/12228225/204079657-6e62872a-2f29-478e-a29b-bcb0a92781a6.png) mysql5.7执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112oae3f5de5b703c6334747befb9ab05349?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0ODc5OSwiaWF0IjoxNjY5MzQzOTk5LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9hZTNmNWRlNWI3MDNjNjMzNDc0N2JlZmI5YWIwNTM0OSJ9.xVaHGnOULNO4uec94RadSs5K8iG0QZVyGD-FvlNraOY) +![image](https://user-images.githubusercontent.com/12228225/204079878-a9885b86-5a44-4ba2-b837-66adc43b07d3.png) #### GETS多条子查询 @@ -524,11 +547,11 @@ http://localhost:8675/lowCodePlatform/forms/api/gets mysql8执行sql语句: -![img](https://tcs-devops.aliyuncs.com/storage/112of22704b782cc932d4f51a144aaddbe76?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9mMjI3MDRiNzgyY2M5MzJkNGY1MWExNDRhYWRkYmU3NiJ9.ejWQb3yK60XBm3zRm4PU077l3lu2jsHjqX5ij0tvS7g) +![image](https://user-images.githubusercontent.com/12228225/204079892-bc71eb65-cfbd-4c3c-bda9-4b31902058ba.png) mysql5.7执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112o331a15eb0b89f8788c2e1369e9ead38a?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0ODg3MSwiaWF0IjoxNjY5MzQ0MDcxLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8zMzFhMTVlYjBiODlmODc4OGMyZTEzNjllOWVhZDM4YSJ9.NZjO2ndpyIW5CdQ3giGL4ylkclWC4VRNtJePIB7hBTs) +![image](https://user-images.githubusercontent.com/12228225/204079897-521a763f-bb08-44af-92c6-5e4117fe9d33.png) #### head 单个子查询 @@ -557,11 +580,11 @@ http://localhost:8675/lowCodePlatform/forms/api/head mysql8执行sql语句: -![img](https://tcs-devops.aliyuncs.com/storage/112o97e7879481ef209d27cd689881ba2dae?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm85N2U3ODc5NDgxZWYyMDlkMjdjZDY4OTg4MWJhMmRhZSJ9.1FsB785CT9VOnKf-Z6NYu6Ouy3DiL0SJm5G0iSHnO94) +![image](https://user-images.githubusercontent.com/12228225/204079903-e397a78a-1849-4678-ac41-0611165a1de1.png) mysql5.7执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112o7b2de6f66df479e2b38f53e25da56b04?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0ODk1NywiaWF0IjoxNjY5MzQ0MTU3LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm83YjJkZTZmNjZkZjQ3OWUyYjM4ZjUzZTI1ZGE1NmIwNCJ9.Nxi3u1TMTYE92FuAnz4srLBLeW8fHt-T0gXIOguAu-Q) +![image](https://user-images.githubusercontent.com/12228225/204079908-1efb5b28-889d-4d9b-b4f9-5092925888c9.png) #### head 多个子查询 @@ -603,19 +626,18 @@ mysql5.7执行结果: mysql8执行sql语句: -![img](https://tcs-devops.aliyuncs.com/storage/112o2da6826648bb92fe52d292e6f98194fe?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8yZGE2ODI2NjQ4YmI5MmZlNTJkMjkyZTZmOTgxOTRmZSJ9.z9t8h2jF9HYrnr-86j61zQmIuzNquNZ1LWD-mKFyOa8) +![image](https://user-images.githubusercontent.com/12228225/204079919-5fba8f87-56d8-4d7d-b457-4a2505f27d1e.png) mysql5.7执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112o0d8df9fbfdc94b6b6f338f080cd4bc19?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0OTAwOCwiaWF0IjoxNjY5MzQ0MjA4LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8wZDhkZjlmYmZkYzk0YjZiNmYzMzhmMDgwY2Q0YmMxOSJ9.3jOg9eJMTRZXIQh3ZFnTsuhu1N4CnoM3CR7t3I6rIn4) +![image](https://user-images.githubusercontent.com/12228225/204079932-1e040caf-57fd-45a7-afa5-b26bdce83fba.png) #### heads 单个子查询 普通获取数量 会执行校验流程, Access、Request需要配置鉴权信息: - -![img](https://tcs-devops.aliyuncs.com/storage/112oe091e1d4376a6fcb62cbce0383cdddf9?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9lMDkxZTFkNDM3NmE2ZmNiNjJjYmNlMDM4M2NkZGRmOSJ9._BSyl8VzN15CTAxr_J1ud0tzYCBQwGQWqaiBRvmau8Q) +![image](https://user-images.githubusercontent.com/12228225/204079942-d790a3c0-eb46-4512-bb58-45a16894608a.png) ``` http://localhost:8675/lowCodePlatform/forms/api/heads @@ -641,17 +663,17 @@ http://localhost:8675/lowCodePlatform/forms/api/heads mysql8执行sql语句: -![img](https://tcs-devops.aliyuncs.com/storage/112offc8ee52b3bd03af5012ae9832ed7800?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9mZmM4ZWU1MmIzYmQwM2FmNTAxMmFlOTgzMmVkNzgwMCJ9.aPpEd5GM5iTIs149Xc2kxovMu82HzbZUHd3L7yrtkQE) +![image](https://user-images.githubusercontent.com/12228225/204079952-976fa9b6-4a11-40ad-a2c7-6f901b186670.png) mysql5.7执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112o1ad0c28563c50c245ee39d399fcbf817?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0OTE3MywiaWF0IjoxNjY5MzQ0MzczLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm8xYWQwYzI4NTYzYzUwYzI0NWVlMzlkMzk5ZmNiZjgxNyJ9.Wc4X-gAhJhKtFDIc15i8Y-JFb6BYy4EBVGNQ0fq2_SE) +![image](https://user-images.githubusercontent.com/12228225/204079959-6bf95b45-5f35-474e-b428-b51bcb5b500d.png) #### heads 多个子查询 会执行校验流程, Access、Request需要配置鉴权信息: -![img](https://tcs-devops.aliyuncs.com/storage/112od6c06bedd0338403de83a3da034862b6?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9kNmMwNmJlZGQwMzM4NDAzZGU4M2EzZGEwMzQ4NjJiNiJ9.c4OVSUGncl_anepEZN1jzHmk7FiIRY-UcRj6EOn0ySk) +![image](https://user-images.githubusercontent.com/12228225/204079967-a48f4f50-6e6b-476b-a281-b072ef8a352d.png) 普通获取数量 @@ -691,13 +713,11 @@ mysql5.7执行结果: mysql8执行sql语句: -![img](https://tcs-devops.aliyuncs.com/storage/112oa28b0fce57d06fea1386164f4183f4df?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IiIsImV4cCI6MTY2OTk0NTcwNiwiaWF0IjoxNjY5MzQwOTA2LCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9hMjhiMGZjZTU3ZDA2ZmVhMTM4NjE2NGY0MTgzZjRkZiJ9.7UtbXd2E6tU6aSicO_LoEhQfPvViN2SCrF2-UdhkHyk) +![image](https://user-images.githubusercontent.com/12228225/204079980-c93ef595-0c4b-42a7-a3b3-1e7402d3cb13.png) mysql5.7执行结果: -![img](https://tcs-devops.aliyuncs.com/storage/112od2bd40102e4250e79caeae832dcacd77?Signature=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBcHBJRCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9hcHBJZCI6IjVlNzQ4MmQ2MjE1MjJiZDVjN2Y5YjMzNSIsIl9vcmdhbml6YXRpb25JZCI6IjYxYmQ0MTk3YWM0MDEyNWFmMGY1ZmJlMyIsImV4cCI6MTY2OTk0OTIzMywiaWF0IjoxNjY5MzQ0NDMzLCJyZXNvdXJjZSI6Ii9zdG9yYWdlLzExMm9kMmJkNDAxMDJlNDI1MGU3OWNhZWFlODMyZGNhY2Q3NyJ9.0mgwZshZSKSxxkak2mJfj8LHrIyjVj2NTKghOVJ0-J0) - - +![image](https://user-images.githubusercontent.com/12228225/204079987-878d5937-3f42-4f59-93dc-b5a840f5548c.png) ### delete、put 支持子查询 @@ -711,11 +731,11 @@ https://github.com/Tencent/APIJSON/issues/471 AbstractVerifier.IS_UPDATE_MUST_HAVE_ID_CONDITION = true; // true: 必须有 -![image-20221126145415115](/Users/xy/Library/Application Support/typora-user-images/image-20221126145415115.png) +![image](https://user-images.githubusercontent.com/12228225/204080001-eef4ee65-0ad0-4a41-93ba-9b16cd1c2e0e.png) 2、细粒度控制 -![image-20221125154603033](/Users/xy/Library/Application Support/typora-user-images/image-20221125154603033.png) +![image](https://user-images.githubusercontent.com/12228225/204080012-f7d781e9-0a53-461f-84db-3d6ecb167e20.png) #### 使用说明 @@ -806,7 +826,7 @@ http://localhost:8675/lowCodePlatform/forms/api/delete } ``` -![image-20221125161720199](/Users/xy/Library/Application Support/typora-user-images/image-20221125161720199.png) +![image](https://user-images.githubusercontent.com/12228225/204080043-6614457c-a0ed-45b3-a26a-e75126dbb486.png) 开启id删除、id引用 删除成功 @@ -828,8 +848,7 @@ http://localhost:8675/lowCodePlatform/forms/api/delete "explan": true } ``` - -![image-20221126145714808](/Users/xy/Library/Application Support/typora-user-images/image-20221126145714808.png) +![image](https://user-images.githubusercontent.com/12228225/204080050-e6f04fe6-319e-45b7-b1b2-bf4cda4ab2db.png) PUT 子查询 修改 @@ -854,7 +873,7 @@ PUT 子查询 修改 } ``` -![image-20221126151726450](/Users/xy/Library/Application Support/typora-user-images/image-20221126151726450.png) +![image](https://user-images.githubusercontent.com/12228225/204080072-8f605595-cd8c-474b-975f-4ac97fb92a26.png) #### bug修复 @@ -866,9 +885,10 @@ mysql8以下 非with-as表达式 会报错: DELETE FROM `housekeeping`.`User` WHERE ( (`username` IN (SELECT * FROM (SELECT `username` FROM `housekeeping`.`User` WHERE ( (`username` = 'test1') )) as a) ) ) -![image](https://user-images.githubusercontent.com/12228225/203517122-3d5b3b90-9780-4e05-b633-b264c575757a.png) +![image](https://user-images.githubusercontent.com/12228225/204080126-e1f7c82a-2f09-409d-b3f2-fe25badea180.png) + +![image](https://user-images.githubusercontent.com/12228225/204080131-0c15404d-3045-4d01-bd89-d2a1f1fa0360.png) -![image](https://user-images.githubusercontent.com/12228225/203517315-4ab11545-4285-4737-92a3-cfd1494e2652.png) ### must、refuses判断、delete、PUT支持 ref @@ -891,4 +911,4 @@ WHERE ( (`username` IN (SELECT * FROM (SELECT `username` FROM `housekeeping`.`Us } ``` -![image-20221125161821101](/Users/xy/Library/Application Support/typora-user-images/image-20221125161821101.png) \ No newline at end of file +![image](https://user-images.githubusercontent.com/12228225/204080150-28972226-37e0-4280-962a-83f7ac12d37c.png) From 883b8d3abfa4b3022a5d5086ee5c988b49e2345c Mon Sep 17 00:00:00 2001 From: cloudAndMonkey Date: Sat, 26 Nov 2022 16:56:16 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20buildTag=20=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIJSONORM/src/main/java/apijson/orm/AbstractParser.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java index 6c8195bf2..41b13c491 100755 --- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java +++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java @@ -2174,14 +2174,14 @@ private JSONObject batchVerify(RequestMethod method, String tag, int version, St } /** - * { "xxx:aa":{ "@tag": "" }, "tag": "User" } + * { "xxx:aa":{ "@tag": "" }} + * 生成规则: * 1、@tag存在,tag=@tag * 2、@tag不存在 - * 生成规则: - * 1、存在别名 + * 1)、存在别名 * key=对象: tag=key去除别名 * key=数组: tag=key去除别名 + [] - * 2、不存在别名 + * 2)、不存在别名 * tag=key * tag=key + [] * @param request