Skip to content

Commit 68bfce0

Browse files
committed
批量新增或批量单独设置修改:新增配置允许部分子项失败;优化 AbstractParser 代码
1 parent dd37279 commit 68bfce0

File tree

6 files changed

+372
-236
lines changed

6 files changed

+372
-236
lines changed

APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java

Lines changed: 111 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public AbstractObjectParser parse(String name, boolean isReuse) throws Exception
211211
functionMap = null;//must init
212212
childMap = null;//must init
213213

214-
Set<Entry<String, Object>> set = request.isEmpty() ? null : new LinkedHashSet<Entry<String, Object>>(request.entrySet());
214+
Set<Entry<String, Object>> set = request.isEmpty() ? null : new LinkedHashSet<>(request.entrySet());
215215
if (set != null && set.isEmpty() == false) {//判断换取少几个变量的初始化是否值得?
216216
if (isTable) {//非Table下必须保证原有顺序!否则 count,page 会丢, total@:"/[]/total" 会在[]:{}前执行!
217217
customMap = new LinkedHashMap<String, Object>();
@@ -360,8 +360,10 @@ public boolean onParse(@NotNull String key, @NotNull Object value) throws Except
360360

361361
JSONObject subquery = (JSONObject) value;
362362
String range = subquery.getString(JSONRequest.KEY_SUBQUERY_RANGE);
363-
if (range != null && JSONRequest.SUBQUERY_RANGE_ALL.equals(range) == false && JSONRequest.SUBQUERY_RANGE_ANY.equals(range) == false) {
364-
throw new IllegalArgumentException("子查询 " + path + "/" + key + ":{ range:value } 中 value 只能为 [" + JSONRequest.SUBQUERY_RANGE_ALL + ", " + JSONRequest.SUBQUERY_RANGE_ANY + "] 中的一个!");
363+
if (range != null && JSONRequest.SUBQUERY_RANGE_ALL.equals(range) == false
364+
&& JSONRequest.SUBQUERY_RANGE_ANY.equals(range) == false) {
365+
throw new IllegalArgumentException("子查询 " + path + "/" + key + ":{ range:value } 中 value 只能为 ["
366+
+ JSONRequest.SUBQUERY_RANGE_ALL + ", " + JSONRequest.SUBQUERY_RANGE_ANY + "] 中的一个!");
365367
}
366368

367369

@@ -375,7 +377,8 @@ public boolean onParse(@NotNull String key, @NotNull Object value) throws Except
375377
String from = subquery.getString(JSONRequest.KEY_SUBQUERY_FROM);
376378
JSONObject arrObj = from == null ? null : obj.getJSONObject(from);
377379
if (arrObj == null) {
378-
throw new IllegalArgumentException("子查询 " + path + "/" + key + ":{ from:value } 中 value 对应的主表对象 " + from + ":{} 不存在!");
380+
throw new IllegalArgumentException("子查询 " + path + "/"
381+
+ key + ":{ from:value } 中 value 对应的主表对象 " + from + ":{} 不存在!");
379382
}
380383
//
381384
SQLConfig cfg = (SQLConfig) arrObj.get(AbstractParser.KEY_CONFIG);
@@ -516,7 +519,8 @@ public JSON onChildParse(int index, String key, JSONObject value) throws Excepti
516519
arrayCount ++;
517520
int maxArrayCount = parser.getMaxArrayCount();
518521
if (arrayCount > maxArrayCount) {
519-
throw new IllegalArgumentException(path + " 内截至 " + key + ":{} 时数组对象 key[]:{} 的数量达到 " + arrayCount + " 已超限,必须在 0-" + maxArrayCount + " 内 !");
522+
throw new IllegalArgumentException(path + " 内截至 " + key + ":{} 时数组对象 key[]:{} "
523+
+ "的数量达到 " + arrayCount + " 已超限,必须在 0-" + maxArrayCount + " 内 !");
520524
}
521525
}
522526

@@ -582,7 +586,7 @@ public void onPUTArrayParse(@NotNull String key, @NotNull JSONArray array) throw
582586
//GET > add all 或 remove all > PUT > remove key
583587

584588
//GET <<<<<<<<<<<<<<<<<<<<<<<<<
585-
JSONObject rq = new JSONObject();
589+
JSONObject rq = new JSONObject(true);
586590
rq.put(JSONRequest.KEY_ID, request.get(JSONRequest.KEY_ID));
587591
rq.put(JSONRequest.KEY_COLUMN, realKey);
588592
JSONObject rp = parseResponse(RequestMethod.GET, table, null, rq, null, false);
@@ -621,55 +625,130 @@ public void onPUTArrayParse(@NotNull String key, @NotNull JSONArray array) throw
621625

622626

623627
@Override
624-
public void onTableArrayParse(String key, JSONArray value) throws Exception {
628+
public void onTableArrayParse(String key, JSONArray valueArray) throws Exception {
625629
String childKey = key.substring(0, key.length() - JSONRequest.KEY_ARRAY.length());
626-
JSONArray valueArray = (JSONArray) value;
627630

628631
int allCount = 0;
629632
JSONArray ids = new JSONArray();
630633

631634
int version = parser.getVersion();
632635
int maxUpdateCount = parser.getMaxUpdateCount();
633636

634-
String idKey = parser.createSQLConfig().getIdKey(); //Table[]: [{}] arrayConfig 为 null
637+
SQLConfig cfg = null; // 不能污染当前的配置 getSQLConfig();
638+
if (cfg == null) { // TODO 每次都创建成本比较高,是否新增 defaultInstance 或者 configInstance 用来专门 getIdKey 等?
639+
cfg = parser.createSQLConfig();
640+
}
641+
642+
String idKey = cfg.getIdKey(); //Table[]: [{}] arrayConfig 为 null
635643
boolean isNeedVerifyContent = parser.isNeedVerifyContent();
636644

645+
cfg.setTable(childKey); // Request 表 structure 中配置 "ALLOW_PARTIAL_UPDATE_FAILED": "Table[],key[],key:alias[]" 自动配置
646+
boolean allowPartialFailed = cfg.allowPartialUpdateFailed();
647+
JSONArray failedIds = allowPartialFailed ? new JSONArray() : null;
648+
649+
int firstFailIndex = -1;
650+
JSONObject firstFailReq = null;
651+
Throwable firstFailThrow = null;
637652
for (int i = 0; i < valueArray.size(); i++) { //只要有一条失败,则抛出异常,全部失败
638653
//TODO 改成一条多 VALUES 的 SQL 性能更高,报错也更会更好处理,更人性化
639654
JSONObject item;
640655
try {
641656
item = valueArray.getJSONObject(i);
657+
if (item == null) {
658+
throw new NullPointerException();
659+
}
642660
}
643661
catch (Exception e) {
644-
throw new UnsupportedDataTypeException("批量新增/修改失败!" + key + "/" + i + ":value 中value不合法!类型必须是 OBJECT ,结构为 {} !");
662+
throw new UnsupportedDataTypeException(
663+
"批量新增/修改失败!" + key + "/" + i + ":value 中value不合法!类型必须是 OBJECT ,结构为 {} !"
664+
);
645665
}
646-
JSONRequest req = new JSONRequest(childKey, item);
647666

648-
//parser.getMaxSQLCount() ? 可能恶意调用接口,把数据库拖死
649-
JSONObject result = (JSONObject) onChildParse(0, "" + i, isNeedVerifyContent == false ? req : parser.parseCorrectRequest(method, childKey, version, "", req, maxUpdateCount, parser));
650-
result = result.getJSONObject(childKey);
651-
//
652-
boolean success = JSONResponse.isSuccess(result);
653-
int count = result == null ? null : result.getIntValue(JSONResponse.KEY_COUNT);
667+
Object id = item.get(idKey);
668+
JSONObject req = new JSONRequest(childKey, item);
669+
JSONObject result = null;
670+
try {
671+
if (isNeedVerifyContent) {
672+
req = parser.parseCorrectRequest(method, childKey, version, "", req, maxUpdateCount, parser);
673+
}
674+
//parser.getMaxSQLCount() ? 可能恶意调用接口,把数据库拖死
675+
result = (JSONObject) onChildParse(0, "" + i, req);
676+
}
677+
catch (Exception e) {
678+
if (allowPartialFailed == false) {
679+
throw e;
680+
}
654681

655-
if (success == false || count != 1) { //如果 code = 200 但 count != 1,不能算成功,掩盖了错误不好排查问题
656-
throw new ServerException("批量新增/修改失败!" + key + "/" + i + ":" + (success ? "成功但 count != 1 !" : (result == null ? "null" : result.getString(JSONResponse.KEY_MSG))));
657-
}
682+
if (firstFailThrow == null) {
683+
firstFailThrow = e;
684+
firstFailReq = valueArray.getJSONObject(i); // item
685+
}
686+
}
687+
688+
result = result == null ? null : result.getJSONObject(childKey);
689+
690+
boolean success = JSONResponse.isSuccess(result);
691+
int count = result == null ? 0 : result.getIntValue(JSONResponse.KEY_COUNT);
692+
if (id == null && result != null) {
693+
id = result.get(idKey);
694+
}
695+
696+
if (success == false || count != 1) { //如果 code = 200 但 count != 1,不能算成功,掩盖了错误不好排查问题
697+
if (allowPartialFailed) {
698+
failedIds.add(id);
699+
if (firstFailIndex < 0) {
700+
firstFailIndex = i;
701+
}
702+
}
703+
else {
704+
throw new ServerException(
705+
"批量新增/修改失败!" + key + "/" + i + ":" + (success ? "成功但 count != 1 !"
706+
: (result == null ? "null" : result.getString(JSONResponse.KEY_MSG))
707+
));
708+
}
709+
}
658710

659-
allCount += count;
660-
ids.add(result.get(idKey));
711+
allCount += 1; // 加了 allowPartialFailed 后 count 可能为 0 allCount += count;
712+
ids.add(id);
661713
}
662714

663-
JSONObject allResult = AbstractParser.newSuccessResult();
664-
allResult.put(JSONResponse.KEY_COUNT, allCount);
665-
allResult.put(idKey + "[]", ids);
715+
int failedCount = failedIds == null ? 0 : failedIds.size();
716+
if (failedCount >= allCount) {
717+
throw new ServerException("批量新增/修改 " + key + ":[] 中 " + allCount + " 个子项全部失败!"
718+
+ "第 " + firstFailIndex + " 项失败原因:" + (firstFailThrow == null ? "" : firstFailThrow.getMessage()));
719+
}
720+
721+
JSONObject allResult = AbstractParser.newSuccessResult();
722+
if (failedCount > 0) {
723+
allResult.put("failedCount", failedCount);
724+
allResult.put("failedIdList", failedIds);
725+
if (firstFailThrow != null) {
726+
if (firstFailThrow instanceof CommonException && firstFailThrow.getCause() != null) {
727+
firstFailThrow = firstFailThrow.getCause();
728+
}
729+
730+
JSONObject failObj = new JSONObject(true);
731+
failObj.put("index", firstFailIndex);
732+
failObj.put(childKey, firstFailReq);
733+
734+
JSONObject obj = AbstractParser.extendErrorResult(failObj, firstFailThrow, parser.isRoot());
735+
if (Log.DEBUG) {
736+
obj.put("trace:throw", firstFailThrow.getClass().getName());
737+
obj.put("trace:stack", firstFailThrow.getStackTrace());
738+
}
739+
allResult.put("firstFailed", obj);
740+
}
741+
}
742+
allResult.put(JSONResponse.KEY_COUNT, allCount);
743+
allResult.put(idKey + "[]", ids);
666744

667745
response.put(childKey, allResult); //不按原样返回,避免数据量过大
668746
}
669747

670748

671749
@Override
672-
public JSONObject parseResponse(RequestMethod method, String table, String alias, JSONObject request, List<Join> joinList, boolean isProcedure) throws Exception {
750+
public JSONObject parseResponse(RequestMethod method, String table, String alias
751+
, JSONObject request, List<Join> joinList, boolean isProcedure) throws Exception {
673752
SQLConfig config = newSQLConfig(method, table, alias, request, joinList, isProcedure);
674753
return parseResponse(config, isProcedure);
675754
}
@@ -818,7 +897,8 @@ public void onFunctionResponse(String type) throws Exception {
818897
//public void parseFunction(String key, String value, String parentPath, String currentName, JSONObject currentObject) throws Exception {
819898
// parseFunction(key, value, parentPath, currentName, currentObject, false);
820899
//}
821-
public void parseFunction(String rawKey, String key, String value, String parentPath, String currentName, JSONObject currentObject, boolean isMinus) throws Exception {
900+
public void parseFunction(String rawKey, String key, String value, String parentPath
901+
, String currentName, JSONObject currentObject, boolean isMinus) throws Exception {
822902
Object result;
823903
boolean containRaw = rawKeyList != null && rawKeyList.contains(rawKey);
824904

@@ -925,8 +1005,10 @@ public JSONObject onSQLExecute() throws Exception {
9251005
}
9261006

9271007
long endTime = System.currentTimeMillis(); // 3ms - 8ms
928-
Log.e(TAG, "\n onSQLExecute <<<<<<<<<<<<<<<<<<<<<<<<<<<<\n for (int i = 1; i < list.size(); i++) startTime = " + startTime
929-
+ "; endTime = " + endTime + "; duration = " + (endTime - startTime) + "\n >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n ");
1008+
Log.e(TAG, "\n onSQLExecute <<<<<<<<<<<<<<<<<<<<<<<<<<<<"
1009+
+ "\n for (int i = 1; i < list.size(); i++) startTime = " + startTime
1010+
+ "; endTime = " + endTime + "; duration = " + (endTime - startTime)
1011+
+ "\n >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n ");
9301012
}
9311013

9321014
parser.putArrayMainCache(arrayPath, rawList);

0 commit comments

Comments
 (0)