2020import java .util .Optional ;
2121
2222import org .apache .ibatis .mapping .ParameterMapping ;
23- import org .apache .ibatis .parsing .GenericTokenParser ;
2423import org .apache .ibatis .session .Configuration ;
2524
2625/**
2726 * @author Clinton Begin
2827 */
2928public class ForEachSqlNode implements SqlNode {
30- public static final String ITEM_PREFIX = "__frch_" ;
3129
3230 private final ExpressionEvaluator evaluator ;
3331 private final String collectionExpression ;
@@ -44,14 +42,16 @@ public class ForEachSqlNode implements SqlNode {
4442 * @deprecated Since 3.5.9, use the {@link #ForEachSqlNode(Configuration, SqlNode, String, Boolean, String, String, String, String, String)}.
4543 */
4644 @ Deprecated
47- public ForEachSqlNode (Configuration configuration , SqlNode contents , String collectionExpression , String index , String item , String open , String close , String separator ) {
45+ public ForEachSqlNode (Configuration configuration , SqlNode contents , String collectionExpression , String index ,
46+ String item , String open , String close , String separator ) {
4847 this (configuration , contents , collectionExpression , null , index , item , open , close , separator );
4948 }
5049
5150 /**
5251 * @since 3.5.9
5352 */
54- public ForEachSqlNode (Configuration configuration , SqlNode contents , String collectionExpression , Boolean nullable , String index , String item , String open , String close , String separator ) {
53+ public ForEachSqlNode (Configuration configuration , SqlNode contents , String collectionExpression , Boolean nullable ,
54+ String index , String item , String open , String close , String separator ) {
5555 this .evaluator = new ExpressionEvaluator ();
5656 this .collectionExpression = collectionExpression ;
5757 this .nullable = nullable ;
@@ -68,7 +68,7 @@ public ForEachSqlNode(Configuration configuration, SqlNode contents, String coll
6868 public boolean apply (DynamicContext context ) {
6969 Map <String , Object > bindings = context .getBindings ();
7070 final Iterable <?> iterable = evaluator .evaluateIterable (collectionExpression , bindings ,
71- Optional .ofNullable (nullable ).orElseGet (configuration ::isNullableOnForEach ));
71+ Optional .ofNullable (nullable ).orElseGet (configuration ::isNullableOnForEach ));
7272 if (iterable == null || !iterable .iterator ().hasNext ()) {
7373 return true ;
7474 }
@@ -82,18 +82,17 @@ public boolean apply(DynamicContext context) {
8282 } else {
8383 scopedContext = new PrefixedContext (context , separator );
8484 }
85- int uniqueNumber = scopedContext .getUniqueNumber ();
8685 // Issue #709
8786 if (o instanceof Map .Entry ) {
8887 @ SuppressWarnings ("unchecked" )
8988 Map .Entry <Object , Object > mapEntry = (Map .Entry <Object , Object >) o ;
90- applyIndex (scopedContext , mapEntry .getKey (), uniqueNumber );
91- applyItem (scopedContext , mapEntry .getValue (), uniqueNumber );
89+ applyIndex (scopedContext , mapEntry .getKey ());
90+ applyItem (scopedContext , mapEntry .getValue ());
9291 } else {
93- applyIndex (scopedContext , i , uniqueNumber );
94- applyItem (scopedContext , o , uniqueNumber );
92+ applyIndex (scopedContext , i );
93+ applyItem (scopedContext , o );
9594 }
96- contents .apply (new FilteredDynamicContext ( configuration , scopedContext , index , item , uniqueNumber ) );
95+ contents .apply (scopedContext );
9796 if (first ) {
9897 first = !((PrefixedContext ) scopedContext ).isPrefixApplied ();
9998 }
@@ -103,17 +102,15 @@ public boolean apply(DynamicContext context) {
103102 return true ;
104103 }
105104
106- private void applyIndex (DynamicContext context , Object o , int i ) {
105+ private void applyIndex (DynamicContext context , Object o ) {
107106 if (index != null ) {
108107 context .bind (index , o );
109- context .bind (itemizeItem (index , i ), o );
110108 }
111109 }
112110
113- private void applyItem (DynamicContext context , Object o , int i ) {
111+ private void applyItem (DynamicContext context , Object o ) {
114112 if (item != null ) {
115113 context .bind (item , o );
116- context .bind (itemizeItem (item , i ), o );
117114 }
118115 }
119116
@@ -129,55 +126,6 @@ private void applyClose(DynamicContext context) {
129126 }
130127 }
131128
132- private static String itemizeItem (String item , int i ) {
133- return ITEM_PREFIX + item + "_" + i ;
134- }
135-
136- private static class FilteredDynamicContext extends DynamicContext {
137- private final DynamicContext delegate ;
138- private final int index ;
139- private final String itemIndex ;
140- private final String item ;
141-
142- public FilteredDynamicContext (Configuration configuration ,DynamicContext delegate , String itemIndex , String item , int i ) {
143- super (configuration , delegate .getParameterObject (), delegate .getParameterType (), delegate .isParamExists ());
144- this .delegate = delegate ;
145- this .index = i ;
146- this .itemIndex = itemIndex ;
147- this .item = item ;
148- this .bindings .putAll (delegate .getBindings ());
149- }
150-
151- @ Override
152- public String getSql () {
153- return delegate .getSql ();
154- }
155-
156- @ Override
157- public void appendSql (String sql ) {
158- GenericTokenParser parser = new GenericTokenParser ("#{" , "}" , content -> {
159- String newContent = content .replaceFirst ("^\\ s*" + item + "(?![^.,:\\ s])" , itemizeItem (item , index ));
160- if (itemIndex != null && newContent .equals (content )) {
161- newContent = content .replaceFirst ("^\\ s*" + itemIndex + "(?![^.,:\\ s])" , itemizeItem (itemIndex , index ));
162- }
163- return "#{" + newContent + "}" ;
164- });
165-
166- delegate .appendSql (parser .parse (sql ));
167- }
168-
169- @ Override
170- public int getUniqueNumber () {
171- return delegate .getUniqueNumber ();
172- }
173-
174- @ Override
175- public List <ParameterMapping > getParameterMappings () {
176- return delegate .getParameterMappings ();
177- }
178- }
179-
180-
181129 private class PrefixedContext extends DynamicContext {
182130 private final DynamicContext delegate ;
183131 private final String prefix ;
@@ -209,11 +157,6 @@ public String getSql() {
209157 return delegate .getSql ();
210158 }
211159
212- @ Override
213- public int getUniqueNumber () {
214- return delegate .getUniqueNumber ();
215- }
216-
217160 @ Override
218161 public List <ParameterMapping > getParameterMappings () {
219162 return delegate .getParameterMappings ();
0 commit comments