@@ -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