1010import java .sql .Blob ;
1111import java .sql .Clob ;
1212import java .sql .Connection ;
13- import java .sql .Date ;
13+ import java .util .Date ;
1414import java .sql .DriverManager ;
1515import java .sql .PreparedStatement ;
1616import java .sql .ResultSet ;
2020import java .sql .Statement ;
2121import java .sql .Time ;
2222import java .sql .Timestamp ;
23+ import java .time .DayOfWeek ;
2324import java .time .LocalDateTime ;
25+ import java .time .Month ;
26+ import java .time .Year ;
2427import java .util .ArrayList ;
2528import java .util .Arrays ;
2629import java .util .Collection ;
@@ -548,7 +551,7 @@ else if (curJoin.isOuterJoin() || curJoin.isAntiJoin()) {
548551 // 副表是按常规条件查询,缓存会导致其它同表同条件对象查询结果集为空 childMap.put(viceSql, new JSONObject()); // 缓存固定空数据,避免后续多余查询
549552 }
550553 else {
551- curItem = ( JSONObject ) childMap .get (viceSql );
554+ curItem = childMap .get (viceSql );
552555 if (curItem == null ) {
553556 curItem = new JSONObject (true );
554557 childMap .put (viceSql , curItem );
@@ -596,8 +599,8 @@ else if (curJoin.isOuterJoin() || curJoin.isAntiJoin()) {
596599
597600 if (isHead == false ) {
598601 // @ APP JOIN 查询副表并缓存到 childMap <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
599- Map <String ,List <JSONObject >> appJoinChildMap = new HashMap <>();
600- childMap .forEach ((viceSql ,item ) -> appJoinChildMap .put (viceSql ,Arrays .asList (item )));
602+ Map <String , List <JSONObject >> appJoinChildMap = new HashMap <>();
603+ childMap .forEach ((viceSql , item ) -> appJoinChildMap .put (viceSql , Arrays .asList (item )));
601604 executeAppJoin (config , resultList , appJoinChildMap );
602605
603606 // @ APP JOIN 查询副表并缓存到 childMap >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@@ -643,24 +646,21 @@ protected void executeAppJoin(SQLConfig config, List<JSONObject> resultList, Map
643646 List <Join > joinList = config .getJoinList ();
644647 if (joinList != null ) {
645648
646- SQLConfig jc ;
647- SQLConfig cc ;
648-
649649 for (Join join : joinList ) {
650650 if (join .isAppJoin () == false ) {
651651 Log .i (TAG , "executeAppJoin for (Join j : joinList) >> j.isAppJoin() == false >> continue;" );
652652 continue ;
653653 }
654654
655- cc = join .getCacheConfig (); //这里用config改了getSQL后再还原很麻烦,所以提前给一个config2更好
655+ SQLConfig cc = join .getCacheConfig (); //这里用config改了getSQL后再还原很麻烦,所以提前给一个config2更好
656656 if (cc == null ) {
657657 if (Log .DEBUG ) {
658658 throw new NullPointerException ("服务器内部错误, executeAppJoin cc == null ! 导致不能缓存 @ APP JOIN 的副表数据!" );
659659 }
660660 continue ;
661661 }
662662
663- jc = join .getJoinConfig ();
663+ SQLConfig jc = join .getJoinConfig ();
664664
665665 List <On > onList = join .getOnList ();
666666 int size = onList == null ? 0 : onList .size ();
@@ -689,8 +689,8 @@ protected void executeAppJoin(SQLConfig config, List<JSONObject> resultList, Map
689689 }
690690
691691 // 替换为 "id{}": [userId1, userId2, userId3...]
692- jc .putWhere (ok , null , false ); // remove orginKey
693- jc .putWhere (on .getKey () + "{}" , targetValueList , true ); // add orginKey {} }
692+ jc .putWhere (ok , null , false ); // remove originKey
693+ jc .putWhere (on .getKey () + "{}" , targetValueList , true ); // add originKey {} }
694694 }
695695 }
696696
@@ -728,25 +728,28 @@ protected void executeAppJoin(SQLConfig config, List<JSONObject> resultList, Map
728728 executedSQLDuration += System .currentTimeMillis () - executedSQLStartTime ;
729729 }
730730
731+ int childCount = cc .getCount ();
732+ int allChildCount = childCount *config .getCount (); // 所有分组子项数量总和
733+ int count = 0 ;
734+
731735 int index = -1 ;
732736
733737 long startTime2 = System .currentTimeMillis ();
734738 ResultSetMetaData rsmd = rs .getMetaData ();
735739 final int length = rsmd .getColumnCount ();
736740 sqlResultDuration += System .currentTimeMillis () - startTime2 ;
737741
738- JSONObject result ;
739- String cacheSql ;
742+ Map <String , Boolean > skipMap = new HashMap <>();
740743
741744 long lastCursorTime = System .currentTimeMillis ();
742- while (rs .next ()) { //FIXME 同时有 @ APP JOIN 和 < 等 SQL JOIN 时,next = false 总是无法进入循环,导致缓存失效,可能是连接池或线程问题
745+ while (( allChildCount <= 0 || count < allChildCount ) && rs .next ()) { //FIXME 同时有 @ APP JOIN 和 < 等 SQL JOIN 时,next = false 总是无法进入循环,导致缓存失效,可能是连接池或线程问题
743746 sqlResultDuration += System .currentTimeMillis () - lastCursorTime ;
744747 lastCursorTime = System .currentTimeMillis ();
745748
746749 index ++;
747750 Log .d (TAG , "\n \n <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n executeAppJoin while (rs.next()){ index = " + index + "\n \n " );
748751
749- result = new JSONObject (true );
752+ JSONObject result = new JSONObject (true );
750753
751754 for (int i = 1 ; i <= length ; i ++) {
752755 result = onPutColumn (jc , rs , rsmd , index , result , i , null , null );
@@ -757,24 +760,33 @@ protected void executeAppJoin(SQLConfig config, List<JSONObject> resultList, Map
757760 Log .d (TAG , "\n executeAppJoin while (rs.next()) { resultList.put( " + index + ", result); "
758761 + "\n >>>>>>>>>>>>>>>>>>>>>>>>>>> \n \n " );
759762
760- //缓存到 childMap
761763 if (onList != null ) {
762- for (On on : onList ) {
764+ for (On on : onList ) { // APP JOIN 应该有且只有一个 ON 条件
763765 String ok = on .getOriginKey ();
764766 String vk = ok .substring (0 , ok .length () - 1 );
765767 //TODO 兼容复杂关联
766768 cc .putWhere (on .getKey (), result .get (on .getKey ()), true );
767769 }
768770 }
769- cacheSql = cc .getSQL (false );
770- List <JSONObject > results = childMap .get (cacheSql );
771- if (results == null ) {
772- results = new ArrayList <>();
773- childMap .put (cacheSql , results );
774- }
775- results .add (result );
776- Log .d (TAG , ">>> executeAppJoin childMap.put('" + cacheSql + "', result); childMap.size() = " + childMap .size ());
777- }
771+
772+ String cacheSql = cc .getSQL (false );
773+ List <JSONObject > results = childMap .get (cacheSql );
774+
775+ if (results == null || skipMap .get (cacheSql ) == null ) { // 避免添加重复数据
776+ results = new ArrayList <>(childCount );
777+ childMap .put (cacheSql , results );
778+ skipMap .put (cacheSql , Boolean .TRUE );
779+ }
780+
781+ if (childCount <= 0 || results .size () < childCount ) { // 避免超过子数组每页数量
782+ // if (count == 1 && results.isEmpty() == false) { // 避免添加重复数据
783+ // results.clear();
784+ // }
785+ results .add (result ); //缓存到 childMap
786+ count ++;
787+ Log .d (TAG , ">>> executeAppJoin childMap.put('" + cacheSql + "', result); childMap.size() = " + childMap .size ());
788+ }
789+ }
778790 }
779791 finally {
780792 if (rs != null ) {
@@ -910,14 +922,20 @@ protected Object getValue(@NotNull SQLConfig config, @NotNull ResultSet rs, @Not
910922 else if (value instanceof Timestamp ) {
911923 value = ((Timestamp ) value ).toString ();
912924 }
913- else if (value instanceof Date ) {
925+ else if (value instanceof Date ) { // java.sql.Date 和 java.sql.Time 都继承 java.util.Date
914926 value = ((Date ) value ).toString ();
915927 }
916- else if (value instanceof Time ) {
917- value = ((Time ) value ).toString ();
928+ else if (value instanceof LocalDateTime ) {
929+ value = ((LocalDateTime ) value ).toString ();
930+ }
931+ else if (value instanceof Year ) {
932+ value = ((Year ) value ).getValue ();
933+ }
934+ else if (value instanceof Month ) {
935+ value = ((Month ) value ).getValue ();
918936 }
919- else if (value instanceof LocalDateTime ) {
920- value = ((LocalDateTime ) value ).toString ();
937+ else if (value instanceof DayOfWeek ) {
938+ value = ((DayOfWeek ) value ).getValue ();
921939 }
922940 else if (value instanceof String && isJSONType (config , rsmd , columnIndex , lable )) { //json String
923941 castToJson = true ;
0 commit comments