diff --git a/APIJSONORM/pom.xml b/APIJSONORM/pom.xml
index b892374e2..4c1041bc9 100755
--- a/APIJSONORM/pom.xml
+++ b/APIJSONORM/pom.xml
@@ -5,7 +5,7 @@
apijson.orm
apijson-orm
- 4.6.6
+ 4.6.7
jar
APIJSONORM
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
index a22c05d5c..be8ef09e3 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
@@ -301,6 +301,9 @@ public JSONObject parseResponse(String request) {
private int queryDepth;
+ // 打印异常日志的标识。线上环境比较敏感,可以通过切换该变量来控制异常栈抛出、错误日志打印。保守起见,该值默认为false。
+ public static boolean isPrintErrorLog = false;
+
/**解析请求json并获取对应结果
* @param request
* @return requestObject
@@ -383,11 +386,12 @@ public JSONObject parseResponse(JSONObject request) {
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
- if (Log.DEBUG) { //用 | 替代 /,避免 APIJSON ORM,APIAuto 等解析路径错误
+ if (isPrintErrorLog) { //用 | 替代 /,避免 APIJSON ORM,APIAuto 等解析路径错误
requestObject.put("sql:generate|cache|execute|maxExecute", getSQLExecutor().getGeneratedSQLCount() + "|" + getSQLExecutor().getCachedSQLCount() + "|" + getSQLExecutor().getExecutedSQLCount() + "|" + getMaxSQLCount());
requestObject.put("depth:count|max", queryDepth + "|" + getMaxQueryDepth());
requestObject.put("time:start|duration|end", startTime + "|" + duration + "|" + endTime);
if (error != null) {
+ Log.d(TAG, String.format("onObjectParse error, error is %s", error.getMessage()));
requestObject.put("throw", error.getClass().getName());
requestObject.put("trace", error.getStackTrace());
}
@@ -397,7 +401,7 @@ public JSONObject parseResponse(JSONObject request) {
//会不会导致原来的session = null? session = null;
- if (Log.DEBUG) {
+ if (isPrintErrorLog) {
Log.d(TAG, "\n\n\n\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n "
+ requestMethod + "/parseResponse request = \n" + requestString + "\n\n");
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java
index a3ff117cf..8966d0132 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java
@@ -27,6 +27,7 @@
import java.util.Map.Entry;
import java.util.Set;
+import apijson.orm.exception.NotExistException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
@@ -209,9 +210,12 @@ public JSONObject execute(@NotNull SQLConfig config, boolean unknowType) throws
executedSQLCount ++;
int updateCount = executeUpdate(config);
+ if (updateCount <= 0) {
+ throw new NotExistException("没权限访问或对象不存在!");
+ }
- result = AbstractParser.newResult(updateCount > 0 ? JSONResponse.CODE_SUCCESS : JSONResponse.CODE_NOT_FOUND
- , updateCount > 0 ? JSONResponse.MSG_SUCCEED : "没权限访问或对象不存在!");
+ // updateCount>0时收集结果。例如更新操作成功时,返回count(affected rows)、id字段
+ result = new JSONObject(true);
//id,id{}至少一个会有,一定会返回,不用抛异常来阻止关联写操作时前面错误导致后面无条件执行!
result.put(JSONResponse.KEY_COUNT, updateCount);//返回修改的记录数
@@ -717,8 +721,8 @@ public Connection getConnection(@NotNull SQLConfig config) throws Exception {
connection = connectionMap.get(config.getDatabase());
if (connection == null || connection.isClosed()) {
Log.i(TAG, "select connection " + (connection == null ? " = null" : ("isClosed = " + connection.isClosed()))) ;
- // PostgreSQL 不允许 cross-database
- connection = DriverManager.getConnection(config.getDBUri(), config.getDBAccount(), config.getDBPassword());
+ // PostgreSQL 不允许 cross-database
+ connection = DriverManager.getConnection(config.getDBUri(), config.getDBAccount(), config.getDBPassword());
connectionMap.put(config.getDatabase(), connection);
}
@@ -823,14 +827,14 @@ public ResultSet executeQuery(@NotNull SQLConfig config) throws Exception {
public int executeUpdate(@NotNull SQLConfig config) throws Exception {
PreparedStatement s = getStatement(config);
int count = s.executeUpdate(); //PreparedStatement 不用传 SQL
-
+
if (config.getMethod() == RequestMethod.POST && config.getId() == null) { //自增id
ResultSet rs = s.getGeneratedKeys();
if (rs != null && rs.next()) {
config.setId(rs.getLong(1));//返回插入的主键id
}
}
-
+
return count;
}
diff --git a/Document.md b/Document.md
index 701932c9b..c7e7be53c 100644
--- a/Document.md
+++ b/Document.md
@@ -318,7 +318,7 @@
3.请求中的 / 需要转义。JSONRequest.java已经用URLEncoder.encode转义,不需要再写;但如果是浏览器或Postman等直接输入url/request,需要把request中的所有 / 都改成 %252F 。下同。
4.code,指返回结果中的状态码,200表示成功,其它都是错误码,值全部都是HTTP标准状态码。下同。
5.msg,指返回结果中的状态信息,对成功结果或错误原因的详细说明。下同。
-6.code和msg总是在返回结果的同一层级成对出现。对所有请求的返回结果都会在最外层有一对总结式code和msg。对非GET类型的请求,返回结果里面的每个JSONObject里都会有一对code和msg说明这个JSONObject的状态。下同。
+6.code和msg总是在返回结果的同一层级成对出现。对所有请求的返回结果都会在最外层有一对总结式code和msg。下同。
7.id等字段对应的值仅供说明,不一定是数据库里存在的,请求里用的是真实存在的值。下同。
@@ -334,7 +334,7 @@ GET:
普通获取数据,
可用浏览器调试 | base_url/get/ | {<
HEAD:
普通获取数量,
可用浏览器调试 | base_url/head/ | {
TableName:{
…
}
}
{…}内为限制条件
例如获取一个 id = 38710 的 User 所发布的 Moment 总数:
{
"Moment":{
"userId":38710
}
}
后端校验通过后自动解析为 SQL 并执行:
`SELECT count(*) FROM Moment WHERE userId=38710 LIMIT 1` | {
TableName:{
"code":200,
"msg":"success",
"count":10
},
"code":200,
"msg":"success"
}
例如
{
"Moment":{
"code":200,
"msg":"success",
"count":10
},
"code":200,
"msg":"success"
}
GETS:
安全/私密获取数据,
用于获取钱包等
对安全性要求高的数据 | base_url/gets/ | 最外层加一个 "tag":tag,其它同GET | 同GET
HEADS:
安全/私密获取数量,
用于获取银行卡数量等
对安全性要求高的数据总数 | base_url/heads/ | 最外层加一个 "tag":tag,其它同HEAD | 同HEAD
-POST:
新增数据 | base_url/post/ | 单个:
{
TableName:{
…
},
"tag":tag
}
{…}中id由后端生成,不能传
例如当前登录用户 38710 发布一个新 Comment:
{
"Comment":{
"momentId":12,
"content":"APIJSON,let interfaces and documents go to hell !",
},
"tag":"Comment"
}
后端校验通过后自动解析为 SQL 并执行:
`INSERT INTO Comment(userId,momentId,content) VALUES(38710,12,'APIJSON,let interfaces and documents go to hell !')`
批量:
{
TableName\[]:\[{
…
}, {
…
}
…
],
"tag":tag
}
{…}中id由后端生成,不能传
例如当前登录用户 82001 发布 2 个 Comment:
{
"Comment\[]":\[{
"momentId":12,
"content":"APIJSON,let interfaces and documents go to hell !"
}, {
"momentId":15,
"content":"APIJSON is a JSON transmision protocol."
}],
"tag":"Comment:[]"
}
后端校验通过后自动解析为 SQL 并执行:
`INSERT INTO Comment(userId,momentId,content) VALUES(82001,12,'APIJSON,let interfaces and documents go to hell !')`
`INSERT INTO Comment(userId,momentId,content) VALUES(82001,15,'APIJSON is a JSON transmision protocol.')` | 单个:
{
TableName:{
"code":200,
"msg":"success",
"id":38710
},
"code":200,
"msg":"success"
}
例如
{
"Comment":{
"code":200,
"msg":"success",
"id":120
},
"code":200,
"msg":"success"
}
批量:
{
TableName:{
"code":200,
"msg":"success",
"count":5,
"id[]":[1, 2, 3, 4, 5]
},
"code":200,
"msg":"success"
}
例如
{
"Comment":{
"code":200,
"msg":"success",
"count":2,
"id[]":\[1, 2]
},
"code":200,
"msg":"success"
}
+POST:
新增数据 | base_url/post/ | 单个:
{
TableName:{
…
},
"tag":tag
}
{…}中id由后端生成,不能传
例如当前登录用户 38710 发布一个新 Comment:
{
"Comment":{
"momentId":12,
"content":"APIJSON,let interfaces and documents go to hell !"
},
"tag":"Comment"
}
后端校验通过后自动解析为 SQL 并执行:
`INSERT INTO Comment(userId,momentId,content) VALUES(38710,12,'APIJSON,let interfaces and documents go to hell !')`
批量:
{
TableName\[]:\[{
…
}, {
…
}
…
],
"tag":tag
}
{…}中id由后端生成,不能传
例如当前登录用户 82001 发布 2 个 Comment:
{
"Comment\[]":\[{
"momentId":12,
"content":"APIJSON,let interfaces and documents go to hell !"
}, {
"momentId":15,
"content":"APIJSON is a JSON transmision protocol."
}],
"tag":"Comment:[]"
}
后端校验通过后自动解析为 SQL 并执行:
`INSERT INTO Comment(userId,momentId,content) VALUES(82001,12,'APIJSON,let interfaces and documents go to hell !')`
`INSERT INTO Comment(userId,momentId,content) VALUES(82001,15,'APIJSON is a JSON transmision protocol.')` | 单个:
{
TableName:{
"code":200,
"msg":"success",
"id":38710
},
"code":200,
"msg":"success"
}
例如
{
"Comment":{
"code":200,
"msg":"success",
"id":120
},
"code":200,
"msg":"success"
}
批量:
{
TableName:{
"code":200,
"msg":"success",
"count":5,
"id[]":[1, 2, 3, 4, 5]
},
"code":200,
"msg":"success"
}
例如
{
"Comment":{
"code":200,
"msg":"success",
"count":2,
"id[]":\[1, 2]
},
"code":200,
"msg":"success"
}
PUT:
修改数据,
只修改所传的字段 | base_url/put/ | {
TableName:{
"id":id,
…
},
"tag":tag
}
{…} 中 id 或 id{} 至少传一个
例如当前登录用户 82001 修改 id = 235 的 Moment 的 content:
{
"Moment":{
"id":235,
"content":"APIJSON,let interfaces and documents go to hell !"
},
"tag":"Moment"
}
后端校验通过后自动解析为 SQL 并执行:
`UPDATE Moment SET content='APIJSON,let interfaces and documents go to hell !' WHERE id=235 AND userId=82001 LIMIT 1`
批量除了 id{}:\[] 也可类似批量 POST,只是每个 {...} 里面都必须有 id。
"tag":"Comment[]" 对应对象 "Comment":{"id{}":[1,2,3]},表示指定记录全部统一设置;
"tag":"Comment:[]" 多了冒号,对应数组 "Comment[]":[{"id":1},{"id":2},{"id":3}],表示每项单独设置 | 同POST
DELETE:
删除数据 | base_url/delete/ | {
TableName:{
"id":id
},
"tag":tag
}
{…} 中 id 或 id{} 至少传一个,一般只传 id 或 id{}
例如当前登录用户 82001 批量删除 id = 100,110,120 的 Comment:
{
"Comment":{
"id{}":[100,110,120]
},
"tag":"Comment[]"
}
后端校验通过后自动解析为 SQL 并执行:
`DELETE FROM Comment WHERE id IN(100,110,120) AND userId=82001 LIMIT 3` | {
TableName:{
"code":200,
"msg":"success",
"id[]":[100,110,120]
"count":3
},
"code":200,
"msg":"success"
}
例如
{
"Comment":{
"code":200,
"msg":"success",
"id[]":[100,110,120],
"count":3
},
"code":200,
"msg":"success"
}