Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

一个json(事务)同时支持新增、修改、删除、查询、别名 #468

Open
cloudAndMonkey opened this issue Nov 10, 2022 · 84 comments
Labels
Enhancement 增强 增强功能、提高性能等

Comments

@cloudAndMonkey
Copy link
Contributor

cloudAndMonkey commented Nov 10, 2022

版本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
image
image
image
该方法,是参数校验入口
image
特定tag,则走分支流程
image
image
修改引用关系
image
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应该能搞定,空了研究一下,哈哈

@TommyLemon
Copy link
Collaborator

赞,感谢分享~

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 10, 2022

把增删改查不同操作放在一个请求 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 等) 对应的默认操作方法

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 11, 2022

@TommyLemon >
临时变量 是以表名为维度
"@post": "Moment,Comment[]", 解决不了同时操作一张表
比如
sys_permission 菜单表
新增一条记录, 要修改父菜单的is_leaf(是否叶子节点:1:是 0:不是)

流程要处理几个地方(还没有细化):
1、校验
2、语句执行
语句执行的地方要能区分一张表不同的 请求操作类型

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 11, 2022

还有一种方法, 通过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 如何打到对象上面跟着语句走

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 11, 2022

目前我能想到比较简单的方式:
key: tag-table-post
语句执行
再想办法将 @post@get 如何打到对象上面跟着语句走

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 11, 2022

@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

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 11, 2022

@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:{} !

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 13, 2022

以前没有这样的需求,现在可以新增支持。
”POST请求,请在 内传 User:{} !“
这个报错是因为 Request 表 structure 中配置的就是 "User":{} 而不是 "User:aa":{}

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 14, 2022

以前没有这样的需求,现在可以新增支持。 ”POST请求,请在 内传 User:{} !“ 这个报错是因为 Request 表 structure 中配置的就是 "User":{} 而不是 "User:aa":{}

嗯嗯,功能我基本调通了,一些细节我还要调整一下,比如 第一条语句 查询 如果没有结果,将会直接返回 等等

@cloudAndMonkey
Copy link
Contributor Author

以前没有这样的需求,现在可以新增支持。 ”POST请求,请在 内传 User:{} !“ 这个报错是因为 Request 表 structure 中配置的就是 "User":{} 而不是 "User:aa":{}
@TommyLemon
单表新增、修改、删除支持别名 #470

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 16, 2022

@TommyLemon
一个json 支持新增(单条、批量)、修改(单条、批量)、删除、查询、别名
实现代码如下:
1、重载 APIJSONParser 实现 parseCorrectRequest
2、注释tag校验
image
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
image
image
示例:
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
}
image
// 新增、修改、删除、查询
// 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
Copy link
Collaborator

@TommyLemon 一个json 支持新增(单条、批量)、修改(单条、批量)、删除、查询、别名 实现代码如下: 1、重载 APIJSONParser 实现 parseCorrectRequest 2、注释tag校验 image 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 image image 示例: 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 } image // 新增、修改、删除、查询 // 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
Copy link
Collaborator

TommyLemon commented Nov 16, 2022

可以最外层新增传参
"transaction": true
来指定有事务,这个全局关键词目前未支持,需要自己实现下。
然后重写 Parser 中
setAutoCommit
begin
commit
rollback
等事务相关方法。

另外建议 @method 值用全大写,例如 "@method": "GET",保持统一的常量/关键词命名风格,也方便复用 enum RequestMethod,例如
RequestMethod.GET.name().equals(method)
或者
RequestMethod.valueOf(method)

@cloudAndMonkey
Copy link
Contributor Author

可以最外层新增传参 "transaction": true 来指定有事务,这个全局关键词目前未支持,需要自己实现下。 然后重写 Parser 中 setAutoCommit begin commit rollback 等事务相关方法。

另外建议 @method 值用全大写,例如 "@method": "GET",保持统一的常量/关键词命名风格,也方便复用 enum RequestMethod,例如 RequestMethod.GET.name().equals(method) 或者 RequestMethod.valueOf(method)

好的,谢谢

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 17, 2022

可以最外层新增传参 "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
image

json解析每一条语句执行,只会改变自己的 transactionIsolation
image
所以只需要在 AbstractParser onCommit 这里改变判断条件即可:
以前是 get请求直接返回,不执行 commit
image
测试示例: 查询、新增

{
    "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
}

执行结果: 事务生效, 数据入库正常
image

@cloudAndMonkey cloudAndMonkey changed the title put、post批量操作不同表源码实现 一个json(支持事务)同时支持新增、修改、删除、查询、别名 Nov 17, 2022
@cloudAndMonkey cloudAndMonkey changed the title 一个json(支持事务)同时支持新增、修改、删除、查询、别名 一个json(事务)同时支持新增、修改、删除、查询、别名 Nov 17, 2022
@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 18, 2022

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

@cloudAndMonkey
Copy link
Contributor Author

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

好的,我先看看

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 22, 2022

我还要稍微调一下
确认一下, 只有GET 查询 使用 with-as表达式吗?
子查询 删除/修改 采用 in的方式?
还是统一都采用with-as表达式?

@TommyLemon
apijson版本: 5.4
mysql8 支持 with as表达式, 提高性能
实现流程图:
image

修改源码: AbstractSQLConfig
image
image
测试用例:
// 测试 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
}
image
mysql5.7执行结果:
image
场景二 多个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
}
image
mysql5.7执行结果:
image
经过相关功能点复测,不影响其他功能点 :
新增、修改、删除、(一个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
}
image
image

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 22, 2022

起码 GET 和 GETS 都支持,可以用 RequestMethod.isGetMethod(method, true) 判断;
还可以也支持 HEAD 和 HEADS,可以用 RequestMethod.isPublicMethod(method, true) 判断。

至于 PUT, DELETE 也可以支持,那就是只要 method != RequestMethod.POST 就都支持,
方便实现根据特定子查询条件来修改/删除数据。

@TommyLemon
Copy link
Collaborator

@cloudAndMonkey
Copy link
Contributor Author

起码 GET 和 GETS 都支持,可以用 RequestMethod.isGetMethod(method, true) 判断; 还可以也支持 HEAD 和 HEADS,可以用 RequestMethod.isPublicMethod(method, true) 判断。

至于 PUT, DELETE 也可以支持,那就是只要 method != RequestMethod.POST 就都支持, 方便实现根据特定子查询条件来修改/删除数据。
@TommyLemon
这几种method 我都搞定了
image

我再测一下, 确认没啥问题, 再提PR
测得我两眼冒金花了
这段时间搞下来, 开源、持续维护、功能版本迭代真不容易呀,能坚持下来都是神人, 哈哈😄

目前已经完成的功能点:
1、delete 非id 、ref引用
2、json(事物) 同时支持新增、修改、删除、查询、别名
3、别名
4、with-as支持

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 23, 2022

起码 GET 和 GETS 都支持,可以用 RequestMethod.isGetMethod(method, true) 判断; 还可以也支持 HEAD 和 HEADS,可以用 RequestMethod.isPublicMethod(method, true) 判断。
至于 PUT, DELETE 也可以支持,那就是只要 method != RequestMethod.POST 就都支持, 方便实现根据特定子查询条件来修改/删除数据。
@TommyLemon
这几种method 我都搞定了
image

我再测一下, 确认没啥问题, 再提PR 测得我两眼冒金花了 这段时间搞下来, 开源、持续维护、功能版本迭代真不容易呀,能坚持下来都是神人, 哈哈😄

目前已经完成的功能点: 1、delete 非id 、ref引用 2、json(事物) 同时支持新增、修改、删除、查询、别名 3、别名 4、with-as支持

@cloudAndMonkey 赞,感谢,期待 PR~
现有功能推荐用 APIAuto 来零代码回归测试,新增功能也可以添加测试 Demo 到 APIAuto
https://github.com/TommyLemon/APIAuto

image

还可以额外配置请求参数生成规则
image

image

@TommyLemon TommyLemon added the Enhancement 增强 增强功能、提高性能等 label Nov 23, 2022
@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 24, 2022

@TommyLemon
apijson版本: 5.4
head 子查询,不会经过校验 ,会将 sql@ 解析为 count(xx)执行, 这是一个bug
image
目前我是通过 "@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格式调整了一下, 按照 上次你说的方式 更合理
image

image

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 24, 2022

赞,可以先提 PR,不用一开始就完美。 done is better than perfect.
敏捷开发,小步快跑。只要每次提交都整体比之前更好就行了,通过不断迭代来趋近完美。
而且据我观察 HEAD/HEADS 这两个本来用户就普遍用得很少,可以暂时先不管。

@cloudAndMonkey
Copy link
Contributor Author

@TommyLemon
单条、批量 put、post多条、delete ,"@Explain": true 无法返回执行sql语句
image
一个json 包含多条语句 , 能正常返回
image

等我空了看看啥原因

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 24, 2022

建议先提个 PR 把功能提交上去,后面再提 PR 修改 bug,一次提交量太大的话往往不好 code review,bug 风险比较高,也不好定位

@cloudAndMonkey
Copy link
Contributor Author

建议先提个 PR 把功能提交上去,后面再提 PR 修改 bug,一次提交量太大的话往往不好 code review,bug 风险比较高,也不好定位

嗯, 我先记下来

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Feb 28, 2023

@Alleyq 没有, 直接用

image 这几个方法是你本地实现的吧,有没有源码贴出来看下

全能crud method , APIJSON6.0 已经支持这些功能, 直接使用

比如如下格式, 你可以配置不同数据源, 相同数据源 非public method 支持事物

{
	"@datasource": "master",
	"@post": {
		"Access": {
			 "tag": "Access"
		},
		"Request[]": {
			 "tag": "Request[]"
		}
	},
    "Access": {
        "name": "Iinterface_list",
         "get": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "head": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "gets": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "heads": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "post": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "put": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "delete": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
        "detail": "接口表"
    },
     "Request[]": [
        {
          "method": "POST",
          "tag": "Iinterface_list",
          "structure": "{\"MUST\": \"name,url,method,appId\", \"UPDATE\": {\"@role\": \"OWNER\"}, \"REFUSE\": \"id\"}",
          "detail": "新增"
        },
        {
          "method": "POST",
          "tag": "Iinterface_list[]",
          "structure": "{\"Iinterface_list[]\": [{\"MUST\": \"name,url,method,appId\", \"REFUSE\": \"id\"}], \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}}",
          "detail": "批量新增"
        },
        {
          "method": "PUT",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"userId\", \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "修改"
        },
        {
          "method": "DELETE",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"!\", \"INSERT\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "批量删除"
        }
      ],
    "@explain": true
}

@Alleyq
Copy link

Alleyq commented Feb 28, 2023

@Alleyq 没有, 直接用

image 这几个方法是你本地实现的吧,有没有源码贴出来看下

全能crud method , APIJSON6.0 已经支持这些功能, 直接使用

比如如下格式, 你可以配置不同数据源, 相同数据源 非public method 支持事物

{
   "@post": "User:aa,User_address[]",
   "User:aa":{
        "username":"test1",
        "password": "123456",
	"state": 1
    },
    "User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "@delete": "User:delUser,User_address:delUserAddress",
    "User:delUser":{
    	"id{}": ["1d863e0f-36ed-4817-98ef-690ea0769cd3"]
    },
    "User_address:delUserAddress": {
    	"id{}": ["75ea25d4-489d-4910-a5c8-8f1d24700887", "8106046c-5b5e-492f-8358-2d52fe47d936"]
    },
    "format": true,
    "@explain": true
}

您好 我的请求示例:
请求地址:
http://localhost:9898/crud
请求参数:
{
"@post": "User:aa",
"User:aa":{
"username":"test1",
"_password": "123456",
},
"format": true,
"@Explain": true
}

请求结果为什么是查询 ,我写的是post请求类型,为什么查询结果是 select?

{
"aa": {
"explain": {
"sql": "SELECT * FROM db_apijson.sys_user WHERE ( (username = 'test1') AND (_password = '123456') ) LIMIT 1",
"list": [
{
"id": 1,
"select_type": "SIMPLE",
"table": "sys_user",
"type": "ALL",
"rows": 2,
"filtered": 50.0,
"Extra": "Using where"
}
]
}
},
"format": true,
"explain": true,
"ok": true,
"code": 200,
"msg": "success",
"debug:info|help": " \n提 bug 请发请求和响应的【完整截屏】,没图的自行解决! \n开发者有限的时间和精力主要放在【维护项目源码和文档】上! \n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!! \n【态度 不文明/不友善】的可能会被踢出群,问题也可能不予解答!!! \n\n 环境信息 \n系统: Windows 10 10.0 \n数据库: DEFAULT_DATABASE = MYSQL \nJDK: 1.8.0_321 amd64 \nAPIJSON: 6.0.0 \n \n【常见问题】:#36 \n【通用文档】:https://github.com/Tencent/APIJSON/blob/master/Document.md \n【视频教程】:https://search.bilibili.com/all?keyword=APIJSON",
"sql:generate|cache|execute|maxExecute": "1|0|1|200",
"depth:count|max": "1|5",
"time:start|duration|end|parse|sql": "1677565710108|572|1677565710680|116|456"
}

@cloudAndMonkey
Copy link
Contributor Author

@Alleyq 没有, 直接用

image 这几个方法是你本地实现的吧,有没有源码贴出来看下

全能crud method , APIJSON6.0 已经支持这些功能, 直接使用
比如如下格式, 你可以配置不同数据源, 相同数据源 非public method 支持事物

{
   "@post": "User:aa,User_address[]",
   "User:aa":{
        "username":"test1",
        "password": "123456",
	"state": 1
    },
    "User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "@delete": "User:delUser,User_address:delUserAddress",
    "User:delUser":{
    	"id{}": ["1d863e0f-36ed-4817-98ef-690ea0769cd3"]
    },
    "User_address:delUserAddress": {
    	"id{}": ["75ea25d4-489d-4910-a5c8-8f1d24700887", "8106046c-5b5e-492f-8358-2d52fe47d936"]
    },
    "format": true,
    "@explain": true
}

您好 我的请求示例: 请求地址: http://localhost:9898/crud 请求参数: { "@post": "User:aa", "User:aa":{ "username":"test1", "_password": "123456", }, "format": true, "@Explain": true }

请求结果为什么是查询 ,我写的是post请求类型,为什么查询结果是 select?

{ "aa": { "explain": { "sql": "SELECT * FROM db_apijson.sys_user WHERE ( (username = 'test1') AND (_password = '123456') ) LIMIT 1", "list": [ { "id": 1, "select_type": "SIMPLE", "table": "sys_user", "type": "ALL", "rows": 2, "filtered": 50.0, "Extra": "Using where" } ] } }, "format": true, "explain": true, "ok": true, "code": 200, "msg": "success", "debug:info|help": " \n提 bug 请发请求和响应的【完整截屏】,没图的自行解决! \n开发者有限的时间和精力主要放在【维护项目源码和文档】上! \n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!! \n【态度 不文明/不友善】的可能会被踢出群,问题也可能不予解答!!! \n\n 环境信息 \n系统: Windows 10 10.0 \n数据库: DEFAULT_DATABASE = MYSQL \nJDK: 1.8.0_321 amd64 \nAPIJSON: 6.0.0 \n \n【常见问题】:#36 \n【通用文档】:https://github.com/Tencent/APIJSON/blob/master/Document.md \n【视频教程】:https://search.bilibili.com/all?keyword=APIJSON", "sql:generate|cache|execute|maxExecute": "1|0|1|200", "depth:count|max": "1|5", "time:start|duration|end|parse|sql": "1677565710108|572|1677565710680|116|456" }

@Alleyq
示例发错了, 你看我重新发的

@Alleyq
Copy link

Alleyq commented Feb 28, 2023

@Alleyq 没有, 直接用

image 这几个方法是你本地实现的吧,有没有源码贴出来看下

全能crud method , APIJSON6.0 已经支持这些功能, 直接使用
比如如下格式, 你可以配置不同数据源, 相同数据源 非public method 支持事物

{
   "@post": "User:aa,User_address[]",
   "User:aa":{
        "username":"test1",
        "password": "123456",
	"state": 1
    },
    "User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "@delete": "User:delUser,User_address:delUserAddress",
    "User:delUser":{
    	"id{}": ["1d863e0f-36ed-4817-98ef-690ea0769cd3"]
    },
    "User_address:delUserAddress": {
    	"id{}": ["75ea25d4-489d-4910-a5c8-8f1d24700887", "8106046c-5b5e-492f-8358-2d52fe47d936"]
    },
    "format": true,
    "@explain": true
}

您好 我的请求示例: 请求地址: http://localhost:9898/crud 请求参数: { "@post": "User:aa", "User:aa":{ "username":"test1", "_password": "123456", }, "format": true, "@Explain": true }
请求结果为什么是查询 ,我写的是post请求类型,为什么查询结果是 select?
{ "aa": { "explain": { "sql": "SELECT * FROM db_apijson.sys_user WHERE ( (username = 'test1') AND (_password = '123456') ) LIMIT 1", "list": [ { "id": 1, "select_type": "SIMPLE", "table": "sys_user", "type": "ALL", "rows": 2, "filtered": 50.0, "Extra": "Using where" } ] } }, "format": true, "explain": true, "ok": true, "code": 200, "msg": "success", "debug:info|help": " \n提 bug 请发请求和响应的【完整截屏】,没图的自行解决! \n开发者有限的时间和精力主要放在【维护项目源码和文档】上! \n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!! \n【态度 不文明/不友善】的可能会被踢出群,问题也可能不予解答!!! \n\n 环境信息 \n系统: Windows 10 10.0 \n数据库: DEFAULT_DATABASE = MYSQL \nJDK: 1.8.0_321 amd64 \nAPIJSON: 6.0.0 \n \n【常见问题】:#36 \n【通用文档】:https://github.com/Tencent/APIJSON/blob/master/Document.md \n【视频教程】:https://search.bilibili.com/all?keyword=APIJSON", "sql:generate|cache|execute|maxExecute": "1|0|1|200", "depth:count|max": "1|5", "time:start|duration|end|parse|sql": "1677565710108|572|1677565710680|116|456" }

@Alleyq 示例发错了, 你看我重新发的

我想问下请求地址是用 /crud 这个方法吗 还是用别的什么方法 ,文档里面没有详细说明这一块 谢谢老哥

@cloudAndMonkey
Copy link
Contributor Author

/crud 这个方法 autoapi 使用示例 和 官网使用示例 要等我空了再加

@Alleyq
Copy link

Alleyq commented Feb 28, 2023

/crud 这个方法 autoapi 使用示例 和 官网使用示例 要等我空了再加
我看了源码 这个@post 只接收 JSONObject
源码:
image

我最后改的传值:

{ "@put": { "UserPrivacy": {} }, "UserPrivacy": { "id": "1", "roles": "li222si" }, "format": true, "@explain": true }
执行结果:
{ "userPrivacy": { "sql": "UPDATEdb_apijson.user_privacySETroles = 'li222si' WHERE ( (id= '1') ) LIMIT 1", "ok": true, "code": 200, "msg": "success", "count": 1, "id": "1" }, "format": true, "explain": true, "ok": true, "code": 200, "msg": "success", }

是不是要重写下源码里面这段代码还是怎么滴,我很郁闷 大哥帮忙解惑

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Feb 28, 2023

你的修改能正常, 改一个post示例测一下呀
重新编辑了示例, 增删改查,跨数据源都可以

{
	"@datasource": "master",
	"@post": {
		"Access": {
			 "tag": "Access"
		},
		"Request[]": {
			 "tag": "Request[]"
		}
	},
    "Access": {
        "name": "Iinterface_list",
         "get": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "head": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "gets": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "heads": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "post": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "put": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "delete": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
        "detail": "接口表"
    },
     "Request[]": [
        {
          "method": "POST",
          "tag": "Iinterface_list",
          "structure": "{\"MUST\": \"name,url,method,appId\", \"UPDATE\": {\"@role\": \"OWNER\"}, \"REFUSE\": \"id\"}",
          "detail": "新增"
        },
        {
          "method": "POST",
          "tag": "Iinterface_list[]",
          "structure": "{\"Iinterface_list[]\": [{\"MUST\": \"name,url,method,appId\", \"REFUSE\": \"id\"}], \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}}",
          "detail": "批量新增"
        },
        {
          "method": "PUT",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"userId\", \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "修改"
        },
        {
          "method": "DELETE",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"!\", \"INSERT\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "批量删除"
        }
      ],
    "@explain": true
}

@Alleyq
Copy link

Alleyq commented Feb 28, 2023

你的修改能正常, 改一个post示例测一下呀 重新编辑了示例, 增删改查,跨数据源都可以

{
	"@datasource": "master",
	"@post": {
		"Access": {
			 "tag": "Access"
		},
		"Request[]": {
			 "tag": "Request[]"
		}
	},
    "Access": {
        "name": "Iinterface_list",
         "get": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "head": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "gets": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "heads": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "post": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "put": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "delete": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
        "detail": "接口表"
    },
     "Request[]": [
        {
          "method": "POST",
          "tag": "Iinterface_list",
          "structure": "{\"MUST\": \"name,url,method,appId\", \"UPDATE\": {\"@role\": \"OWNER\"}, \"REFUSE\": \"id\"}",
          "detail": "新增"
        },
        {
          "method": "POST",
          "tag": "Iinterface_list[]",
          "structure": "{\"Iinterface_list[]\": [{\"MUST\": \"name,url,method,appId\", \"REFUSE\": \"id\"}], \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}}",
          "detail": "批量新增"
        },
        {
          "method": "PUT",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"userId\", \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "修改"
        },
        {
          "method": "DELETE",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"!\", \"INSERT\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "批量删除"
        }
      ],
    "@explain": true
}

看到啦 , 感谢感谢 ~

@Alleyq
Copy link

Alleyq commented Mar 2, 2023

你的修改能正常, 改一个post示例测一下呀 重新编辑了示例, 增删改查,跨数据源都可以

{
	"@datasource": "master",
	"@post": {
		"Access": {
			 "tag": "Access"
		},
		"Request[]": {
			 "tag": "Request[]"
		}
	},
    "Access": {
        "name": "Iinterface_list",
         "get": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "head": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "gets": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "heads": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "post": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "put": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
                "delete": "[\"OWNER\", \"ADMIN\",\"LOGIN\"]",
        "detail": "接口表"
    },
     "Request[]": [
        {
          "method": "POST",
          "tag": "Iinterface_list",
          "structure": "{\"MUST\": \"name,url,method,appId\", \"UPDATE\": {\"@role\": \"OWNER\"}, \"REFUSE\": \"id\"}",
          "detail": "新增"
        },
        {
          "method": "POST",
          "tag": "Iinterface_list[]",
          "structure": "{\"Iinterface_list[]\": [{\"MUST\": \"name,url,method,appId\", \"REFUSE\": \"id\"}], \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}}",
          "detail": "批量新增"
        },
        {
          "method": "PUT",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"userId\", \"UPDATE\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "修改"
        },
        {
          "method": "DELETE",
          "tag": "Iinterface_list",
          "structure": "{\"Iinterface_list\":{ \"MUST\":\"id\",\"REFUSE\": \"!\", \"INSERT\": {\"@role\": \"OWNER,ADMIN\"}} }",
          "detail": "批量删除"
        }
      ],
    "@explain": true
}

看到啦 , 感谢感谢 ~

老哥,如果同时新增两张表,第二个表的某个字段引用第一个表的新增主键,这个要怎么写呢?下面是我的代码
{ "@post": { "User": {}, "UserPrivacy": {} }, "User": { "nickName": "all2ey1", "phone": "18576496089", "sex": "2", "userName": "alley" }, "UserPrivacy": { "userId@":"User/id" } }
执行提示: "msg": "POST 请求必须在Table内设置要保存的 key:value !",

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Mar 2, 2023

1、引用主表id, 配置 id 由应用生成,比如uuid
https://github.com/cloudAndMonkey/APIJSON-Demo/blob/master/APIJSON-Java-Server/APIJSONBoot/src/main/java/apijson/demo/DemoSQLConfig.java#L91-L95
2、引用方式如下:

"User:aa":{
        "username":"test-3",
        "password": "233223",
		"state": 1
    },
"User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd"
    	}
    ]

至于 数据库生成id 引用, 看看官网文档, 测一下

@Alleyq
Copy link

Alleyq commented Mar 3, 2023

1、引用主表id, 配置 id 由应用生成,比如uuid https://github.com/cloudAndMonkey/APIJSON-Demo/blob/master/APIJSON-Java-Server/APIJSONBoot/src/main/java/apijson/demo/DemoSQLConfig.java#L91-L95 2、引用方式如下:

"User:aa":{
        "username":"test-3",
        "password": "233223",
		"state": 1
    },
"User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd"
    	}
    ]

至于 数据库生成id 引用, 看看官网文档, 测一下

老哥 批量新增这个条数限制,如果改源码的话会有性能的问题吗 ?

@cloudAndMonkey
Copy link
Contributor Author

1、引用主表id, 配置 id 由应用生成,比如uuid https://github.com/cloudAndMonkey/APIJSON-Demo/blob/master/APIJSON-Java-Server/APIJSONBoot/src/main/java/apijson/demo/DemoSQLConfig.java#L91-L95 2、引用方式如下:

"User:aa":{
        "username":"test-3",
        "password": "233223",
		"state": 1
    },
"User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd"
    	}
    ]

至于 数据库生成id 引用, 看看官网文档, 测一下

老哥 批量新增这个条数限制,如果改源码的话会有性能的问题吗 ?

不用改源码,子类实现方法即可
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#LL69-L110

@wahowaho
Copy link
Contributor

版本6.0.0的APIJSON
您好:这种格式的请求现在不适配了吗
123123123
2222222
我看每个子json都是单独解析的
333331

@TommyLemon
Copy link
Collaborator

TommyLemon commented Apr 12, 2023

版本6.0.0的APIJSON 您好:这种格式的请求现在不适配了吗 123123123 2222222 我看每个子json都是单独解析的 333331

@wahowaho
是个新引入的 bug
#512

这里不应该只 requestItem.put(_key, obj),丢了 "Request":{} 对象导致 objectVerify 抛异常,
应该把原始请求的所有键值对 put 进去,可以 requestItem.putAll(原来的 request 对象)。

可以改下源码试试,如果可以麻烦提 PR 贡献下代码哦,开源要大家一起参与贡献才会更美好~
https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md

image

@cloudAndMonkey
Copy link
Contributor Author

版本6.0.0的APIJSON 您好:这种格式的请求现在不适配了吗 123123123 2222222 我看每个子json都是单独解析的 333331

@wahowaho 是个新引入的 bug #512

这里不应该只 requestItem.put(_key, obj),丢了 "Request":{} 对象导致 objectVerify 抛异常, 应该把原始请求的所有键值对 put 进去,可以 requestItem.putAll(原来的 request 对象)。

可以改下源码试试,如果可以麻烦提 PR 贡献下代码哦,开源要大家一起参与贡献才会更美好~ https://github.com/Tencent/APIJSON/blob/master/CONTRIBUTING.md

image

我来看看

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Apr 13, 2023

为啥每个 JSONObject 进行解析, 一方面是为了解决别名

{
    "Access:a":{
        "id": "1"
    },
    "Request:b":{
        "id@": "/Access/id"
    },
    "tag": "Request"
}

@TommyLemon
Copy link
Collaborator

TommyLemon commented Apr 13, 2023

为啥每个 JSONObject 进行解析, 一方面是为了解决别名

{
    "Access:a":{
        "id": "1"
    },
    "Request:b":{
        "id@": "/Access/id"
    },
    "tag": "Request"
}

@cloudAndMonkey
别名不用提前解析,同一层没有重复表名的话建议不用别名.
如果有别名,也可以直接在 Request 表 structure 字段里配置:

{
    "Access:a":{
        "MUST": "id"
    },
    "Request:b":{
        "UPDATE": {
            "id@": "/Access/id"
        }
    }
}

@cloudAndMonkey
Copy link
Contributor Author

为啥每个 JSONObject 进行解析, 一方面是为了解决别名

{
    "Access:a":{
        "id": "1"
    },
    "Request:b":{
        "id@": "/Access/id"
    },
    "tag": "Request"
}

@cloudAndMonkey 别名不用提前解析,同一层没有重复表名的话建议不用别名. 如果有别名,也可以直接在 Request 表 structure 字段里配置:

{
    "Access:a":{
        "MUST": "id"
    },
    "Request:b":{
        "UPDATE": {
            "id@": "/Access/id"
        }
    }
}

那我测一下, crud 和其他方法都统一这么做

@TommyLemon
Copy link
Collaborator

TommyLemon commented Apr 13, 2023

@cloudAndMonkey
刚刚 @wahowaho 提了个修复的 PR:
#545

@cloudAndMonkey
Copy link
Contributor Author

@cloudAndMonkey 刚刚 @wahowaho 提了个修复的 PR: #545

嗯嗯, 看到了, 需要删除tag 、JSONObject 别名判断的代码 , 今天晚上我好好梳理一下

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Apr 13, 2023

@TommyLemon
无别名
image

有别名
image

差不多改好了, 我拉通测一下,需要覆盖各种场景, 把 function 事物一起完善,再提交
比如: Comment:[] 支持别名等

INSERT INTO `apijson`.`Request` (`id`, `debug`, `version`, `method`, `tag`, `structure`, `detail`, `date`) VALUES (45, 0, 2, 'POST', 'Comment:[]', '{\"TYPE\": {\"Comment[]\": \"OBJECT[]\"}, \"INSERT\": {\"@role\": \"OWNER\"}, \"Comment[]\": []}', NULL, '2020-03-01 13:40:04');

最近有点忙, 不好意思😄

@cloudAndMonkey
Copy link
Contributor Author

@TommyLemon
代码已经提交

image

把 \ 去掉了, 代码在报错

TommyLemon added a commit to APIJSON/APIJSON-Demo that referenced this issue Sep 2, 2023
通过 @method: "POST", @gets: { "Privacy":"Privacy-CIRCLE", "User": { "@ROLE":"LOGIN", "tag":"User" } } 等关键词指定。具体文档见:
Tencent/APIJSON#468
@TommyLemon
Copy link
Collaborator

TommyLemon commented Sep 2, 2023

完善同一个请求内多种不同操作的关键词,新增支持

@post: "User", // 相当于 "User": { "tag": "User" }
@gets: { 
    "Privacy": "Privacy-phone" // 相当于 "Privacy": { "tag": "Privacy-phone" }
} 

等简化写法
eccf252

@15207126400
Copy link

求助两位大佬,请问主键非id情况下需要单另外配置什么信息,目前主键为xxx_id,增删改均报错Unknown column 'id' in 'field list'

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Sep 20, 2023

@15207126400

求助两位大佬,请问主键非id情况下需要单另外配置什么信息,目前主键为xxx_id,增删改均报错Unknown column 'id' in 'field list'

image

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Enhancement 增强 增强功能、提高性能等
Projects
None yet
Development

No branches or pull requests

6 participants