Skip to content
New issue

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

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

Already on GitHub? Sign in 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 风险比较高,也不好定位

嗯, 我先记下来

@Alleyq
Copy link

Alleyq commented Feb 28, 2023

@Alleyq 没有, 直接用

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

@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

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

No branches or pull requests

6 participants