一个json(事务)同时支持新增、修改、删除、查询、别名
版本5.2.0
1、业务表-插入不同表1:1、1:n、n:n
2、业务表-修改不同表1:1、1:n、n:n
3、业务表-批量删除不同表
实现流程:
1、继承APIJSONParser
2、重载 parseCorrectRequest方法
User__User 通过__分割, tag 和 structure的类名
新增, tag和 structure的类名一样, 更多示例请参见postman
该方法,是参数校验入口
特定tag,则走分支流程
修改引用关系
postman测试示例:
业务表-插入不同表1:1-源码实现
{
"User__User":{
"username":"test2",
"password": "123456",
"state": 1
},
"User_address__User_address":
{
"user_id@": "User/id",
"addr": "ddd",
"count": 1
},
"tag": "Batch_Tag_UserWithUser_addressList"
}
业务表-插入不同表1:n-源码实现
{
"User__User":{
"username":"test1",
"password": "123456",
"state": 1
},
"User_address[]__User_address[]": [
{
"user_id@": "User/id",
"addr": "ddd",
"count": 1
},
{
"user_id@": "User/id",
"addr": "ddd1",
"count": 2
}
],
"tag": "Batch_Tag_UserWithUser_addressList"
}
业务表-插入不同表n:n-源码实现
{
"User[]__User[]":[
{
"username":"test3",
"password": "123456",
"state": 1
},
{
"username":"test4",
"password": "123456",
"state": 1
}
],
"User_address[]__User_address[]": [
{
"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
"addr": "ddd",
"count": 1
},
{
"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
"addr": "ddd1",
"count": 2
}
],
"tag": "Batch_Tag_UserWithUser_addressList"
}
业务表-批量修改不同表1:n-源码实现
{
"User__User":{
"id": "94593122-403a-4eb2-a6f0-182ed3da7764",
"username":"test1-1",
"password": "111111",
"state": 1
},
"User_address[]__User_address[]": [
{
"id": "e8bb9e79-9bbe-49d2-9542-77792368bece",
"user_id@": "User/id",
"addr": "addr-01",
"count": 1
},
{
"id": "4dfee57f-6953-4371-865f-22b6e1957fee",
"user_id@": "User/id",
"addr": "addr-11",
"count": 1
}
],
"tag": "Batch_Tag_UserWithUser_addressList"
}
业务表-批量修改不同表n:n-源码实现
{
"User[]__User[]":[
{
"id": "f60e829a-1181-4331-ac1e-f5faf64e3a8c",
"username":"test-3",
"password": "123456-1",
"state": 1
},
{
"id": "ca86a2e0-d504-4772-b06a-1a8c9e2b12c9",
"username":"test-4",
"password": "123456-1",
"state": 1
}
],
"User_address[]__User_address[]": [
{
"id": "faf8a605-66a3-4ce1-b774-c499b86a4984",
"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
"addr": "ddd-1",
"count": 1
},
{
"id": "ac88ce16-6cdf-41a3-b382-c78452c5a850",
"user_id": "94593122-403a-4eb2-a6f0-182ed3da7764",
"addr": "ddd-2",
"count": 2
}
],
"tag": "Batch_Tag_UserWithUser_addressList"
}
业务表-批量删除不同表-源码实现
{
"User[]__User":{
"id{}": ["8e44c04a-6e90-4dfe-b021-3436453c55dd", "94593122-403a-4eb2-a6f0-182ed3da7764","ca86a2e0-d504-4772-b06a-1a8c9e2b12c9"]
},
"User_address[]__User_address": {
"id{}": ["1ed2dda1-5800-4b69-b128-7771dd79046f", "e8bb9e79-9bbe-49d2-9542-77792368bece","4dfee57f-6953-4371-865f-22b6e1957fee","faf8a605-66a3-4ce1-b774-c499b86a4984"]
},
"tag": "Batch_Tag_UserWithUser_addressList"
}
后续我再研究一下 1、支持不同的操作类型,比如 GET、POST、DELETE, 在一个json里面, 才能保证事物 2、function函数 执行语句, 加入事物 框架能支持数组, 把数组拆解为一条一条语句执行, 只要把相关引用 传递进 function应该能搞定,空了研究一下,哈哈
赞,感谢分享~
把增删改查不同操作放在一个请求 JSON 中,需要额外字段来标记,例如可以是
{
"Moment": {
"@method": "POST",
// TODO 其它字段
},
"Comment[]": [
{
"@method": "PUT",
// TODO 其它字段
}
]
}
或者这样更好一些,可以提前知道那些片段属于哪种操作,方便解析,性能也更好:
{
"@post": "Moment,Comment[]", // 分发到 POST 请求对应的解析处理
"Moment": {
// TODO 其它字段
},
"Comment[]": [
{
// TODO 其它字段
}
],
"@get": "User", // 分发到 GET 请求对应的解析处理
"User": {
// TODO 其它字段
},
"Privacy": { // 按 URL 对应的默认方法处理
// TODO 其它字段
}
}
对于没有显式声明操作方法的,直接用 URL(/get, /post 等) 对应的默认操作方法
@TommyLemon > 临时变量 是以表名为维度 "@post": "Moment,Comment[]", 解决不了同时操作一张表 比如 sys_permission 菜单表 新增一条记录, 要修改父菜单的is_leaf(是否叶子节点:1:是 0:不是)
流程要处理几个地方(还没有细化): 1、校验 2、语句执行 语句执行的地方要能区分一张表不同的 请求操作类型
还有一种方法, 通过request structure 字段来支持,通过json格式匹配 1、校验 { "post": [ {"Table_order_list_test": {"MUST":"aa,dd","UPDATE": {"@role": "OWNER,ADMIN","pwdEncrypt-()": "pwdEncrypt(id,password)"}, "REFUSE": "id"}}, {"User[]": {"User[]": [{"MUST":"username,password","REFUSE": "id"}], "UPDATE": {"@role": "OWNER,ADMIN"}}} ] "put": [ {"Table_order_list_test": {"MUST":"aa,dd","UPDATE": {"@role": "OWNER,ADMIN","pwdEncrypt-()": "pwdEncrypt(id,password)"}, "REFUSE": "id"}}, {"User[]": {"User[]": [{"MUST":"username,password","REFUSE": "id"}], "UPDATE": {"@role": "OWNER,ADMIN"}}} ] } 2、语句执行 将 @post、@get 如何打到对象上面跟着语句走
目前我能想到比较简单的方式: key: tag-table-post 语句执行 再想办法将 @post、@get 如何打到对象上面跟着语句走
@TommyLemon > 临时变量 是以表名为维度 "@post": "Moment,Comment[]", 解决不了同时操作一张表 比如 sys_permission 菜单表 新增一条记录, 要修改父菜单的is_leaf(是否叶子节点:1:是 0:不是)
流程要处理几个地方(还没有细化): 1、校验 2、语句执行 语句执行的地方要能区分一张表不同的 请求操作类型
对同一张表可以用别名来区分不同记录,例如:
{
"User": {
//TODO 其它字段
},
"User:owner": {
"@role": "OWNER",
//TODO 其它字段
},
"User:count": {
"@column": "count(1)",
//TODO 其它字段
}
}
具体见 通用文档 > 3.设计规范 > 3.2 功能符 > 新建别名 https://github.com/Tencent/APIJSON/blob/master/Document.md#3.2
@TommyLemon >
"name:alias",name映射为alias,用alias替代name。可用于 column,Table,SQL函数 等。只用于GET类型、HEAD类型的请求
post请求, 没办法传递 别名呀
{
"User:aa":{
"username":"test",
"password": "233223",
"state": 1
},
"tag": "User"
}
{"User:aa":{"username":"test","password":"233223","state":1},"format":true} java.lang.UnsupportedOperationException: POST请求,请在 内传 User:{} !
以前没有这样的需求,现在可以新增支持。 ”POST请求,请在 内传 User:{} !“ 这个报错是因为 Request 表 structure 中配置的就是 "User":{} 而不是 "User:aa":{}
以前没有这样的需求,现在可以新增支持。 ”POST请求,请在 内传 User:{} !“ 这个报错是因为 Request 表 structure 中配置的就是 "User":{} 而不是 "User:aa":{}
嗯嗯,功能我基本调通了,一些细节我还要调整一下,比如 第一条语句 查询 如果没有结果,将会直接返回 等等
以前没有这样的需求,现在可以新增支持。 ”POST请求,请在 内传 User:{} !“ 这个报错是因为 Request 表 structure 中配置的就是 "User":{} 而不是 "User:aa":{} @TommyLemon 单表新增、修改、删除支持别名 #470
@TommyLemon
一个json 支持新增(单条、批量)、修改(单条、批量)、删除、查询、别名
实现代码如下:
1、重载 APIJSONParser 实现 parseCorrectRequest
2、注释tag校验
3、FormParser
实现单条、批量校验逻辑
`/**
* 相同对象,通过别名区分
* @param method
* @param tag
* @param version
* @param name
* @param request
* @param maxUpdateCount
* @param creator
* @return
* @throws Exception
*/
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);
String _tag = null;
if (request.keySet() == null || request.keySet().size() == 0) {
throw new IllegalArgumentException("json对象格式不正确 !,例如 "User": {}");
}
for (String key : request.keySet()) {
// key重复直接抛错
if (jsonObject.containsKey(key)) {
throw new IllegalArgumentException("json对象名重复,请添加操作类型区分!,例如 method__tag__structureKey, 或者: tag__structureKey");
}
if(key.startsWith("@") || key.endsWith("@")) {
jsonObject.put(key, request.get(key));
continue;
}
// 处理别名
if(request.get(key) instanceof JSONObject || request.get(key) instanceof JSONArray) {
String tmpKey = key;
if(apijson.JSONObject.isTableArray(key)) {
tmpKey = (key.substring(0, key.length() - apijson.JSONObject.KEY_ARRAY.length()));
}
if(tableAlias.get(tmpKey) == null) {
int keyIndex = tmpKey.indexOf(":");
if(keyIndex != -1) {
tableAlias.put(tmpKey, tmpKey.substring(0, keyIndex));
}
}
}
// 获取执行方法
if (request.get(key) instanceof JSONObject) {
String _method = request.getJSONObject(key).getString("@method");
if(_method != null) {
method = RequestMethod.valueOf(_method.toUpperCase());
}
// 判断是否为get请求
if (RequestMethod.isPublicMethod(method)) {
jsonObject.put(key, request.getJSONObject(key));
continue;
}
// 非get请求,则进行参数校验
String tmpTag = request.getJSONObject(key).getString("@tag");
if(tmpTag != null) {
_tag = tmpTag;
}else if(StringUtil.isEmpty(tag)) {
// 批量操作 tag[] = key[]
if(apijson.JSONObject.isTableArray(key)) {
String tmpKey = (key.substring(0, key.length() - apijson.JSONObject.KEY_ARRAY.length()));
if(tableAlias.get(tmpKey) != null) {
_tag = tableAlias.get(tmpKey) + apijson.JSONObject.KEY_ARRAY;
}else {
// 不存在别名
_tag = key;
}
}else {
// 单条操作, tag = key
if(tableAlias.get(key) != null) {
_tag = tableAlias.get(key);
}else {
// 不存在别名
_tag = key;
}
}
}else {
// 数组解析成对象,会进入
if(tableAlias.get(tag) != null) {
_tag = tableAlias.get(tag);
}else {
_tag = tag;
}
}
JSONObject requestItem = new JSONObject();
requestItem.put(_tag, request.get(key));
JSONObject object = getLocalStructure(method, _tag, version);
JSONObject ret = commonVerify(method, _tag, version, name, requestItem, maxUpdateCount, creator, object);
jsonObject.put(key, ret.getJSONObject(_tag));
}else if(request.get(key) instanceof JSONArray) {
jsonObject.put(key, request.getJSONArray(key));
}else {
jsonObject.put(key, request.get(key));
}
}
return jsonObject;
}`
4、修改 AbstractParser
示例:
sql层级最多5层
// 新增、修改、删除
// 执行sql语句条数不能超过5条
{
"User:aa":{
"@method": "POST",
"username":"test1",
"password": "123456",
"state": 1
},
"User_address[]": [
{
"@method": "POST",
"user_id@": "User:aa/id",
"addr": "ddd",
"count": 1
},
{
"@method": "POST",
"user_id@": "User:aa/id",
"addr": "ddd1",
"count": 2
}
],
"User_address:modifUA":
{
"@method": "PUT",
"id": "1c051f08-4671-4fef-8ae3-64fc8b45047d",
"user_id@": "User:aa/id",
"addr": "addr-01",
"count": 1
},
"User:delUser":{
"@method": "DELETE",
"id{}": ["1d42c09c-0780-4762-8100-a718d7c8a83b", "a1d51e2a-797c-4b3f-afc4-45befcd775ed"]
},
"@explain": true
}
// 新增、修改、删除、查询
// get请求会导致事物无法提交(看需要是否支持)
// get请求最好放到前置函数里面操作,通过前置函数来回填需要新增、修改的参数
{
"User:aa":{
"@method": "POST",
"username":"test1",
"password": "123456",
"state": 1
},
"User_address[]": [
{
"@method": "POST",
"user_id@": "User:aa/id",
"addr": "ddd",
"count": 1
},
{
"@method": "POST",
"user_id@": "User:aa/id",
"addr": "ddd1",
"count": 2
}
],
"sql@": {
"@method": "GET",
"with": true,
"from": "User",
"User": {
"@column": "id",
"id{}": ["834df81e-cf8b-40a5-9638-c62fb00e8db4"]
}
},
"User_address:sUA[]": {
"@method": "GET",
"User_address": {
"user_id{}@": "sql"
},
"page": 0,
"count": 10,
"query": 2
},
"total@": "/User_address:sUA[]/total",
"@explain": true
}
多条查询:
{
"sql@": {
"@method": "GET",
"with": true,
"from": "User",
"User": {
"@column": "id",
"id{}": ["64c09bdc-927a-411b-843f-ff3f72b5d5be"]
}
},
"User_address:ua[]": {
"@method": "GET",
"User_address": {
"user_id{}@": "sql"
},
"page": 0,
"count": 10,
"query": 2
},
"total@": "/User_address:ua[]/total",
"sql1@": {
"@method": "GET",
"with": true,
"from": "User",
"User": {
"@column": "id",
"id{}": ["64c09bdc-927a-411b-843f-ff3f72b5d5be"]
}
},
"User_address:ua1[]": {
"@method": "GET",
"User_address": {
"user_id{}@": "sql1"
},
"page": 0,
"count": 10,
"query": 2
},
"total1@": "/User_address:ua1[]/total",
"@explain": true
}
@TommyLemon 一个json 支持新增(单条、批量)、修改(单条、批量)、删除、查询、别名 实现代码如下: 1、重载 APIJSONParser 实现 parseCorrectRequest 2、注释tag校验
3、FormParser 实现单条、批量校验逻辑 /** * 相同对象,通过别名区分 * @param method * @param tag * @param version * @param name * @param request * @param maxUpdateCount * @param creator * @return * @throws Exception */ 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); String _tag = null; if (request.keySet() == null || request.keySet().size() == 0) { throw new IllegalArgumentException("json对象格式不正确 !,例如 "User": {}"); } for (String key : request.keySet()) { // key重复直接抛错 if (jsonObject.containsKey(key)) { throw new IllegalArgumentException("json对象名重复,请添加操作类型区分!,例如 method__tag__structureKey, 或者: tag__structureKey"); }
if(key.startsWith("@") || key.endsWith("@")) { jsonObject.put(key, request.get(key)); continue; } // 处理别名 if(request.get(key) instanceof JSONObject || request.get(key) instanceof JSONArray) { String tmpKey = key; if(apijson.JSONObject.isTableArray(key)) { tmpKey = (key.substring(0, key.length() - apijson.JSONObject.KEY_ARRAY.length())); } if(tableAlias.get(tmpKey) == null) { int keyIndex = tmpKey.indexOf(":"); if(keyIndex != -1) { tableAlias.put(tmpKey, tmpKey.substring(0, keyIndex)); } } } // 获取执行方法 if (request.get(key) instanceof JSONObject) { String _method = request.getJSONObject(key).getString("@method"); if(_method != null) { method = RequestMethod.valueOf(_method.toUpperCase()); } // 判断是否为get请求 if (RequestMethod.isPublicMethod(method)) { jsonObject.put(key, request.getJSONObject(key)); continue; } // 非get请求,则进行参数校验 String tmpTag = request.getJSONObject(key).getString("@tag"); if(tmpTag != null) { _tag = tmpTag; }else if(StringUtil.isEmpty(tag)) { // 批量操作 tag[] = key[] if(apijson.JSONObject.isTableArray(key)) { String tmpKey = (key.substring(0, key.length() - apijson.JSONObject.KEY_ARRAY.length())); if(tableAlias.get(tmpKey) != null) { _tag = tableAlias.get(tmpKey) + apijson.JSONObject.KEY_ARRAY; }else { // 不存在别名 _tag = key; } }else { // 单条操作, tag = key if(tableAlias.get(key) != null) { _tag = tableAlias.get(key); }else { // 不存在别名 _tag = key; } } }else { // 数组解析成对象,会进入 if(tableAlias.get(tag) != null) { _tag = tableAlias.get(tag); }else { _tag = tag; } } JSONObject requestItem = new JSONObject(); requestItem.put(_tag, request.get(key)); JSONObject object = getLocalStructure(method, _tag, version); JSONObject ret = commonVerify(method, _tag, version, name, requestItem, maxUpdateCount, creator, object); jsonObject.put(key, ret.getJSONObject(_tag)); }else if(request.get(key) instanceof JSONArray) { jsonObject.put(key, request.getJSONArray(key)); }else { jsonObject.put(key, request.get(key)); } } return jsonObject; }4、修改 AbstractParser
![]()
示例: sql层级最多5层 // 新增、修改、删除 // 执行sql语句条数不能超过5条 { "User:aa":{ "@method": "post", "username":"test1", "password": "123456", "state": 1 }, "User_address[]": [ { "@method": "post", "user_id@": "User:aa/id", "addr": "ddd", "count": 1 }, { "@method": "post", "user_id@": "User:aa/id", "addr": "ddd1", "count": 2 } ], "User_address:modifUA": { "@method": "put", "id": "1c051f08-4671-4fef-8ae3-64fc8b45047d", "user_id@": "User:aa/id", "addr": "addr-01", "count": 1 }, "User:delUser":{ "@method": "delete", "id{}": ["1d42c09c-0780-4762-8100-a718d7c8a83b", "a1d51e2a-797c-4b3f-afc4-45befcd775ed"] }, "@Explain": true }
// 新增、修改、删除、查询 // get请求会导致事物无法提交(看需要是否支持) // get请求最好放到前置函数里面操作,通过前置函数来回填需要新增、修改的参数 { "User:aa":{ "@method": "post", "username":"test1", "password": "123456", "state": 1 }, "User_address[]": [ { "@method": "post", "user_id@": "User:aa/id", "addr": "ddd", "count": 1 }, { "@method": "post", "user_id@": "User:aa/id", "addr": "ddd1", "count": 2 } ], "sql@": { "@method": "get", "with": true, "from": "User", "User": { "@column": "id", "id{}": ["834df81e-cf8b-40a5-9638-c62fb00e8db4"] } }, "User_address:sUA[]": { "@method": "get", "User_address": { "user_id{}@": "sql" }, "page": 0, "count": 10, "query": 2 }, "total@": "/User_address:sUA[]/total", "@Explain": true } 多条查询: { "sql@": { "@method": "get", "with": true, "from": "User", "User": { "@column": "id", "id{}": ["64c09bdc-927a-411b-843f-ff3f72b5d5be"] } }, "User_address:ua[]": { "@method": "get", "User_address": { "user_id{}@": "sql" }, "page": 0, "count": 10, "query": 2 }, "total@": "/User_address:ua[]/total", "sql1@": { "@method": "get", "with": true, "from": "User", "User": { "@column": "id", "id{}": ["64c09bdc-927a-411b-843f-ff3f72b5d5be"] } }, "User_address:ua1[]": { "@method": "get", "User_address": { "user_id{}@": "sql1" }, "page": 0, "count": 10, "query": 2 }, "total1@": "/User_address:ua1[]/total", "@Explain": true }
赞,感谢分享~
可以最外层新增传参 "transaction": true 来指定有事务,这个全局关键词目前未支持,需要自己实现下。 然后重写 Parser 中 setAutoCommit begin commit rollback 等事务相关方法。
另外建议 @method 值用全大写,例如 "@method": "GET",保持统一的常量/关键词命名风格,也方便复用 enum RequestMethod,例如 RequestMethod.GET.name().equals(method) 或者 RequestMethod.valueOf(method)
可以最外层新增传参 "transaction": true 来指定有事务,这个全局关键词目前未支持,需要自己实现下。 然后重写 Parser 中 setAutoCommit begin commit rollback 等事务相关方法。
另外建议 @method 值用全大写,例如 "@method": "GET",保持统一的常量/关键词命名风格,也方便复用 enum RequestMethod,例如 RequestMethod.GET.name().equals(method) 或者 RequestMethod.valueOf(method)
好的,谢谢
可以最外层新增传参 "transaction": true 来指定有事务,这个全局关键词目前未支持,需要自己实现下。 然后重写 Parser 中 setAutoCommit begin commit rollback 等事务相关方法。
另外建议 @method 值用全大写,例如 "@method": "GET",保持统一的常量/关键词命名风格,也方便复用 enum RequestMethod,例如 RequestMethod.GET.name().equals(method) 或者 RequestMethod.valueOf(method)
@TommyLemon
json第一次执行,会设置 AbstractSQLExecutor transactionIsolation , GET = 0 , 其他= 4

json解析每一条语句执行,只会改变自己的 transactionIsolation
所以只需要在 AbstractParser onCommit 这里改变判断条件即可:
以前是 get请求直接返回,不执行 commit
测试示例: 查询、新增
{
"sql@": {
"@method": "GET",
"with": true,
"from": "User",
"User": {
"@column": "id",
"id{}": ["c692d9d1-2e23-4055-99fb-66461bda33c3"]
}
},
"User_address:uad[]": {
"@method": "GET",
"User_address": {
"user_id{}@": "sql"
},
"page": 0,
"count": 10,
"query": 2
},
"total@": "/User_address:uad[]/total",
"User:aa":{
"@method": "POST",
"username":"test1",
"password": "123456",
"state": 1
},
"User_address:uad1[]": [
{
"@method": "POST",
"user_id@": "User:aa/id",
"addr": "ddd",
"count": 1
},
{
"@method": "POST",
"user_id@": "User:aa/id",
"addr": "ddd1",
"count": 2
}
],
"@explain": true
}
执行结果: 事务生效, 数据入库正常

你把 WITH(SELECT ...) AS `sql` 也实现了嘛?
https://github.com/Tencent/APIJSON/blob/master/Roadmap.md

你把 WITH(SELECT ...) AS
sql也实现了嘛? https://github.com/Tencent/APIJSON/blob/master/Roadmap.md
好的,我先看看
我还要稍微调一下 确认一下, 只有GET 查询 使用 with-as表达式吗? 子查询 删除/修改 采用 in的方式? 还是统一都采用with-as表达式?
@TommyLemon
apijson版本: 5.4
mysql8 支持 with as表达式, 提高性能
实现流程图:

修改源码: AbstractSQLConfig
测试用例:
// 测试 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
}
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
}
mysql5.7执行结果:
经过相关功能点复测,不影响其他功能点 :
新增、修改、删除、(一个json包含新增、修改、删除)
例如(不想看可以忽略,举一个复杂测试示例):
{
"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"
}
},
"Sys_user:sy":{
"@method": "POST",
"username":"test-4",
"password": "123456",
"status": 1
},
"Sys_role:sr":
{
"@method": "POST",
"role_name": "角色-4",
"role_code": "1111-4",
"description": "角色-4"
},
"Sys_user_role:sur":{
"@method": "POST",
"user_id@": "Sys_user:sy/id",
"role_id@": "Sys_role:sr/id"
},
"@explain": true
}

起码 GET 和 GETS 都支持,可以用 RequestMethod.isGetMethod(method, true) 判断; 还可以也支持 HEAD 和 HEADS,可以用 RequestMethod.isPublicMethod(method, true) 判断。
至于 PUT, DELETE 也可以支持,那就是只要 method != RequestMethod.POST 就都支持, 方便实现根据特定子查询条件来修改/删除数据。
麻烦提个 PR 贡献代码哦,开源要大家一起参与贡献才会更美好~

https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md#%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%80%E5%AE%9A%E8%A6%81%E8%B4%A1%E7%8C%AE%E4%BB%A3%E7%A0%81
起码 GET 和 GETS 都支持,可以用 RequestMethod.isGetMethod(method, true) 判断; 还可以也支持 HEAD 和 HEADS,可以用 RequestMethod.isPublicMethod(method, true) 判断。
至于 PUT, DELETE 也可以支持,那就是只要 method != RequestMethod.POST 就都支持, 方便实现根据特定子查询条件来修改/删除数据。 @TommyLemon 这几种method 我都搞定了
我再测一下, 确认没啥问题, 再提PR 测得我两眼冒金花了 这段时间搞下来, 开源、持续维护、功能版本迭代真不容易呀,能坚持下来都是神人, 哈哈😄
目前已经完成的功能点: 1、delete 非id 、ref引用 2、json(事物) 同时支持新增、修改、删除、查询、别名 3、别名 4、with-as支持
起码 GET 和 GETS 都支持,可以用 RequestMethod.isGetMethod(method, true) 判断; 还可以也支持 HEAD 和 HEADS,可以用 RequestMethod.isPublicMethod(method, true) 判断。 至于 PUT, DELETE 也可以支持,那就是只要 method != RequestMethod.POST 就都支持, 方便实现根据特定子查询条件来修改/删除数据。 @TommyLemon 这几种method 我都搞定了
我再测一下, 确认没啥问题, 再提PR 测得我两眼冒金花了 这段时间搞下来, 开源、持续维护、功能版本迭代真不容易呀,能坚持下来都是神人, 哈哈😄
目前已经完成的功能点: 1、delete 非id 、ref引用 2、json(事物) 同时支持新增、修改、删除、查询、别名 3、别名 4、with-as支持
@cloudAndMonkey 赞,感谢,期待 PR~ 现有功能推荐用 APIAuto 来零代码回归测试,新增功能也可以添加测试 Demo 到 APIAuto https://github.com/TommyLemon/APIAuto
还可以额外配置请求参数生成规则

@TommyLemon
apijson版本: 5.4
head 子查询,不会经过校验 ,会将 sql@ 解析为 count(xx)执行, 这是一个bug
目前我是通过 "@method": "GET", 来控制的,你看是否需要调整?
{
"sql@": {
"@method": "GET",
"with": true,
"from": "Sys_user_role",
"Sys_user_role": {
"@column": "role_id",
"user_id": "4732209c-5785-4827-b532-5092f154fd94"
}
},
"Sys_role": {
"id{}@": "sql"
},
"@explain": true
}
另外, 我把一个json支持 不同操作,json格式调整了一下, 按照 上次你说的方式 更合理


赞,可以先提 PR,不用一开始就完美。 done is better than perfect. 敏捷开发,小步快跑。只要每次提交都整体比之前更好就行了,通过不断迭代来趋近完美。 而且据我观察 HEAD/HEADS 这两个本来用户就普遍用得很少,可以暂时先不管。
@TommyLemon
单条、批量 put、post多条、delete ,"@explain": true 无法返回执行sql语句
一个json 包含多条语句 , 能正常返回

等我空了看看啥原因
建议先提个 PR 把功能提交上去,后面再提 PR 修改 bug,一次提交量太大的话往往不好 code review,bug 风险比较高,也不好定位
建议先提个 PR 把功能提交上去,后面再提 PR 修改 bug,一次提交量太大的话往往不好 code review,bug 风险比较高,也不好定位
嗯, 我先记下来
批量插入 "@explain": true支持, 数组解析为单条sql语句的时候, 将 全局"@explain": true打入 单条sql语句, 返回结果的时候,再处理一下,应该就可以了

@TommyLemon batch json (一个json包含增删改查), 应该独立一个 controller方法,新定义一个 method, 自动解析 每个对象/数组/@sql等 不同的method,走不同的流程. 我测下来, 如果url method = delete , json里面包含增删改查, 数组插入并不会执行. url put、post能走完整流程
如果一个json支持 不同的method 操作 1、如果配置"@Explain" 能够看到一个事物中的所有执行sql语句 2、前置函数 前置函数能够将json语句, 像数组一样,解析成每一条语句 加入到 事物中
