View Javadoc
1   /*
2    *    Copyright 2009-2024 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       https://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.apache.ibatis.executor;
17  
18  import java.util.ArrayList;
19  import java.util.Date;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.apache.ibatis.builder.StaticSqlSource;
25  import org.apache.ibatis.cache.Cache;
26  import org.apache.ibatis.cache.decorators.LoggingCache;
27  import org.apache.ibatis.cache.decorators.ScheduledCache;
28  import org.apache.ibatis.cache.decorators.SerializedCache;
29  import org.apache.ibatis.cache.decorators.SynchronizedCache;
30  import org.apache.ibatis.cache.impl.PerpetualCache;
31  import org.apache.ibatis.domain.blog.Author;
32  import org.apache.ibatis.domain.blog.Blog;
33  import org.apache.ibatis.domain.blog.Comment;
34  import org.apache.ibatis.domain.blog.Post;
35  import org.apache.ibatis.domain.blog.Section;
36  import org.apache.ibatis.domain.blog.Tag;
37  import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
38  import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
39  import org.apache.ibatis.mapping.Discriminator;
40  import org.apache.ibatis.mapping.MappedStatement;
41  import org.apache.ibatis.mapping.ParameterMap;
42  import org.apache.ibatis.mapping.ParameterMapping;
43  import org.apache.ibatis.mapping.ParameterMode;
44  import org.apache.ibatis.mapping.ResultFlag;
45  import org.apache.ibatis.mapping.ResultMap;
46  import org.apache.ibatis.mapping.ResultMapping;
47  import org.apache.ibatis.mapping.SqlCommandType;
48  import org.apache.ibatis.mapping.SqlSource;
49  import org.apache.ibatis.mapping.StatementType;
50  import org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
51  import org.apache.ibatis.scripting.xmltags.TextSqlNode;
52  import org.apache.ibatis.session.Configuration;
53  import org.apache.ibatis.type.JdbcType;
54  import org.apache.ibatis.type.TypeHandlerRegistry;
55  
56  final class ExecutorTestHelper {
57  
58    static final Cache authorCache;
59  
60    static {
61      authorCache = new SynchronizedCache(
62          new SerializedCache(new LoggingCache(new ScheduledCache(new PerpetualCache("author_cache")))));
63  
64    }
65  
66    static MappedStatement prepareInsertAuthorMappedStatement(final Configuration config) {
67      final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
68      return new MappedStatement.Builder(config, "insertAuthor",
69          new StaticSqlSource(config,
70              "INSERT INTO author (id,username,password,email,bio,favourite_section) values(?,?,?,?,?,?)"),
71          SqlCommandType.INSERT).parameterMap(
72              new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<ParameterMapping>() {
73                private static final long serialVersionUID = 1L;
74                {
75                  add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
76                  add(new ParameterMapping.Builder(config, "username", registry.getTypeHandler(String.class)).build());
77                  add(new ParameterMapping.Builder(config, "password", registry.getTypeHandler(String.class)).build());
78                  add(new ParameterMapping.Builder(config, "email", registry.getTypeHandler(String.class)).build());
79                  add(new ParameterMapping.Builder(config, "bio", registry.getTypeHandler(String.class))
80                      .jdbcType(JdbcType.VARCHAR).build());
81                  add(new ParameterMapping.Builder(config, "favouriteSection", registry.getTypeHandler(Section.class))
82                      .jdbcType(JdbcType.VARCHAR).build());
83                }
84              }).build()).cache(authorCache).build();
85    }
86  
87    static MappedStatement prepareInsertAuthorMappedStatementWithAutoKey(final Configuration config) {
88      final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
89      return new MappedStatement.Builder(config, "insertAuthor",
90          new StaticSqlSource(config,
91              "INSERT INTO author (username,password,email,bio,favourite_section) values(?,?,?,?,?)"),
92          SqlCommandType.INSERT).parameterMap(
93              new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<ParameterMapping>() {
94                private static final long serialVersionUID = 1L;
95                {
96                  add(new ParameterMapping.Builder(config, "username", registry.getTypeHandler(String.class)).build());
97                  add(new ParameterMapping.Builder(config, "password", registry.getTypeHandler(String.class)).build());
98                  add(new ParameterMapping.Builder(config, "email", registry.getTypeHandler(String.class)).build());
99                  add(new ParameterMapping.Builder(config, "bio", registry.getTypeHandler(String.class))
100                     .jdbcType(JdbcType.VARCHAR).build());
101                 add(new ParameterMapping.Builder(config, "favouriteSection", registry.getTypeHandler(Section.class))
102                     .jdbcType(JdbcType.VARCHAR).build());
103               }
104             }).build()).cache(authorCache).keyGenerator(Jdbc3KeyGenerator.INSTANCE).keyProperty("id").build();
105   }
106 
107   static MappedStatement prepareInsertAuthorProc(final Configuration config) {
108     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
109     return new MappedStatement.Builder(config, "insertAuthorProc",
110         new StaticSqlSource(config, "{call insertAuthor(?,?,?,?)}"), SqlCommandType.INSERT).parameterMap(
111             new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<ParameterMapping>() {
112               private static final long serialVersionUID = 1L;
113               {
114                 add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
115                 add(new ParameterMapping.Builder(config, "username", registry.getTypeHandler(String.class)).build());
116                 add(new ParameterMapping.Builder(config, "password", registry.getTypeHandler(String.class)).build());
117                 add(new ParameterMapping.Builder(config, "email", registry.getTypeHandler(String.class)).build());
118               }
119             }).build()).cache(authorCache).build();
120   }
121 
122   static MappedStatement prepareUpdateAuthorMappedStatement(final Configuration config) {
123     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
124     return new MappedStatement.Builder(config, "updateAuthor",
125         new StaticSqlSource(config, "UPDATE author SET username = ?, password = ?, email = ?, bio = ? WHERE id = ?"),
126         SqlCommandType.UPDATE).parameterMap(
127             new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<ParameterMapping>() {
128               private static final long serialVersionUID = 1L;
129               {
130                 add(new ParameterMapping.Builder(config, "username", registry.getTypeHandler(String.class)).build());
131                 add(new ParameterMapping.Builder(config, "password", registry.getTypeHandler(String.class)).build());
132                 add(new ParameterMapping.Builder(config, "email", registry.getTypeHandler(String.class)).build());
133                 add(new ParameterMapping.Builder(config, "bio", registry.getTypeHandler(String.class))
134                     .jdbcType(JdbcType.VARCHAR).build());
135                 add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
136               }
137             }).build()).cache(authorCache).build();
138   }
139 
140   static MappedStatement prepareDeleteAuthorMappedStatement(final Configuration config) {
141     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
142     return new MappedStatement.Builder(config, "deleteAuthor",
143         new StaticSqlSource(config, "DELETE FROM author WHERE id = ?"), SqlCommandType.DELETE).parameterMap(
144             new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<ParameterMapping>() {
145               private static final long serialVersionUID = 1L;
146               {
147                 add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
148               }
149             }).build()).cache(authorCache).build();
150   }
151 
152   static MappedStatement prepareSelectOneAuthorMappedStatement(final Configuration config) {
153     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
154 
155     final ResultMap rm = new ResultMap.Builder(config, "defaultResultMap", Author.class,
156         new ArrayList<ResultMapping>() {
157           private static final long serialVersionUID = 1L;
158           {
159             add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class)).build());
160             add(new ResultMapping.Builder(config, "username", "username", registry.getTypeHandler(String.class))
161                 .build());
162             add(new ResultMapping.Builder(config, "password", "password", registry.getTypeHandler(String.class))
163                 .build());
164             add(new ResultMapping.Builder(config, "email", "email", registry.getTypeHandler(String.class)).build());
165             add(new ResultMapping.Builder(config, "bio", "bio", registry.getTypeHandler(String.class)).build());
166             add(new ResultMapping.Builder(config, "favouriteSection", "favourite_section",
167                 registry.getTypeHandler(Section.class)).build());
168           }
169         }).build();
170 
171     return new MappedStatement.Builder(config, "selectAuthor",
172         new StaticSqlSource(config, "SELECT * FROM author WHERE id = ?"), SqlCommandType.SELECT).parameterMap(
173             new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<ParameterMapping>() {
174               private static final long serialVersionUID = 1L;
175               {
176                 add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
177               }
178             }).build()).resultMaps(new ArrayList<ResultMap>() {
179               private static final long serialVersionUID = 1L;
180               {
181                 add(rm);
182               }
183             }).cache(authorCache).build();
184   }
185 
186   static MappedStatement prepareSelectAllAuthorsAutoMappedStatement(final Configuration config) {
187     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
188     return new MappedStatement.Builder(config, "selectAuthorAutoMap",
189         new StaticSqlSource(config, "SELECT * FROM author ORDER BY id"), SqlCommandType.SELECT)
190             .resultMaps(new ArrayList<ResultMap>() {
191               private static final long serialVersionUID = 1L;
192               {
193                 add(new ResultMap.Builder(config, "defaultResultMap", Author.class, new ArrayList<ResultMapping>() {
194                   private static final long serialVersionUID = 1L;
195                   {
196                     add(new ResultMapping.Builder(config, "favouriteSection", "favourite_section",
197                         registry.getTypeHandler(Section.class)).build());
198                     add(new ResultMapping.Builder(config, null, "not_exists", Object.class).build());
199                   }
200                 }).build());
201               }
202             }).fetchSize(1000).timeout(2000).build();
203   }
204 
205   static MappedStatement prepareSelectOneAuthorMappedStatementWithConstructorResults(final Configuration config) {
206     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
207     return new MappedStatement.Builder(config, "selectAuthor",
208         new StaticSqlSource(config, "SELECT * FROM author WHERE id = ?"), SqlCommandType.SELECT).parameterMap(
209             new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<ParameterMapping>() {
210               private static final long serialVersionUID = 1L;
211               {
212                 add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
213               }
214             }).build()).resultMaps(new ArrayList<ResultMap>() {
215               private static final long serialVersionUID = 1L;
216               {
217                 add(new ResultMap.Builder(config, "defaultResultMap", Author.class, new ArrayList<ResultMapping>() {
218                   private static final long serialVersionUID = 1L;
219                   {
220                     add(new ResultMapping.Builder(config, null, "id", registry.getTypeHandler(Integer.class))
221                         .javaType(int.class).flags(new ArrayList<ResultFlag>() {
222                           private static final long serialVersionUID = 1L;
223                           {
224                             add(ResultFlag.CONSTRUCTOR);
225                           }
226                         }).build());
227                     add(new ResultMapping.Builder(config, "username", "username", registry.getTypeHandler(String.class))
228                         .build());
229                     add(new ResultMapping.Builder(config, "password", "password", registry.getTypeHandler(String.class))
230                         .build());
231                     add(new ResultMapping.Builder(config, "email", "email", registry.getTypeHandler(String.class))
232                         .build());
233                     add(new ResultMapping.Builder(config, "bio", "bio", registry.getTypeHandler(String.class)).build());
234                     add(new ResultMapping.Builder(config, "favouriteSection", "favourite_section",
235                         registry.getTypeHandler(Section.class)).build());
236                   }
237                 }).build());
238               }
239             }).cache(authorCache).build();
240   }
241 
242   static MappedStatement prepareSelectTwoSetsOfAuthorsProc(final Configuration config) {
243     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
244     return new MappedStatement.Builder(config, "selectTwoSetsOfAuthors",
245         new StaticSqlSource(config, "{call selectTwoSetsOfAuthors(?,?)}"), SqlCommandType.SELECT)
246             .statementType(StatementType.CALLABLE).parameterMap(new ParameterMap.Builder(config, "defaultParameterMap",
247                 Author.class, new ArrayList<ParameterMapping>() {
248                   private static final long serialVersionUID = 1L;
249                   {
250                     add(new ParameterMapping.Builder(config, "id1", registry.getTypeHandler(int.class)).build());
251                     add(new ParameterMapping.Builder(config, "id2", registry.getTypeHandler(int.class)).build());
252                   }
253                 }).build())
254             .resultMaps(new ArrayList<ResultMap>() {
255               private static final long serialVersionUID = 1L;
256               {
257                 ResultMap map = new ResultMap.Builder(config, "defaultResultMap", Author.class,
258                     new ArrayList<ResultMapping>() {
259                       private static final long serialVersionUID = 1L;
260                       {
261                         add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class)).build());
262                         add(new ResultMapping.Builder(config, "username", "username",
263                             registry.getTypeHandler(String.class)).build());
264                         add(new ResultMapping.Builder(config, "password", "password",
265                             registry.getTypeHandler(String.class)).build());
266                         add(new ResultMapping.Builder(config, "email", "email", registry.getTypeHandler(String.class))
267                             .build());
268                         add(new ResultMapping.Builder(config, "bio", "bio", registry.getTypeHandler(String.class))
269                             .build());
270                       }
271                     }).build();
272                 add(map);
273                 add(map);
274               }
275             }).build();
276   }
277 
278   static MappedStatement prepareSelectAuthorViaOutParams(final Configuration config) {
279     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
280     return new MappedStatement.Builder(config, "selectAuthorViaOutParams",
281         new StaticSqlSource(config, "{call selectAuthorViaOutParams(?,?,?,?,?)}"), SqlCommandType.SELECT)
282             .statementType(StatementType.CALLABLE).parameterMap(new ParameterMap.Builder(config, "defaultParameterMap",
283                 Author.class, new ArrayList<ParameterMapping>() {
284                   private static final long serialVersionUID = 1L;
285                   {
286                     add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
287                     add(new ParameterMapping.Builder(config, "username", registry.getTypeHandler(String.class))
288                         .jdbcType(JdbcType.VARCHAR).mode(ParameterMode.OUT).build());
289                     add(new ParameterMapping.Builder(config, "password", registry.getTypeHandler(String.class))
290                         .jdbcType(JdbcType.VARCHAR).mode(ParameterMode.OUT).build());
291                     add(new ParameterMapping.Builder(config, "email", registry.getTypeHandler(String.class))
292                         .jdbcType(JdbcType.VARCHAR).mode(ParameterMode.OUT).build());
293                     add(new ParameterMapping.Builder(config, "bio", registry.getTypeHandler(String.class))
294                         .jdbcType(JdbcType.VARCHAR).mode(ParameterMode.OUT).build());
295                   }
296                 }).build())
297             .resultMaps(new ArrayList<>()).cache(authorCache).build();
298   }
299 
300   static MappedStatement prepareSelectDiscriminatedPost(final Configuration config) {
301     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
302     final ResultMap discriminatorResultMap = new ResultMap.Builder(config, "postResultMap", HashMap.class,
303         new ArrayList<ResultMapping>() {
304           private static final long serialVersionUID = 1L;
305           {
306             add(new ResultMapping.Builder(config, "subject", "subject", registry.getTypeHandler(String.class)).build());
307             add(new ResultMapping.Builder(config, "body", "body", registry.getTypeHandler(String.class)).build());
308           }
309         }).build();
310     config.addResultMap(discriminatorResultMap);
311     return new MappedStatement.Builder(config, "selectPosts", new StaticSqlSource(config, "SELECT * FROM post"),
312         SqlCommandType.SELECT).resultMaps(new ArrayList<ResultMap>() {
313           private static final long serialVersionUID = 1L;
314           {
315             add(new ResultMap.Builder(config, "defaultResultMap", HashMap.class, new ArrayList<ResultMapping>() {
316               private static final long serialVersionUID = 1L;
317               {
318                 add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class)).build());
319                 add(new ResultMapping.Builder(config, "blog_id", "blog_id", registry.getTypeHandler(int.class))
320                     .build());
321               }
322             }).discriminator(new Discriminator.Builder(config,
323                 new ResultMapping.Builder(config, "section", "section", registry.getTypeHandler(String.class)).build(),
324                 new HashMap<String, String>() {
325                   private static final long serialVersionUID = 1L;
326                   {
327                     put("NEWS", discriminatorResultMap.getId());
328                     put("VIDEOS", discriminatorResultMap.getId());
329                     put("PODCASTS", discriminatorResultMap.getId());
330                     // IMAGES left out on purpose.
331                   }
332                 }).build()).build());
333 
334           }
335         }).build();
336   }
337 
338   static MappedStatement createInsertAuthorWithIDof99MappedStatement(final Configuration config) {
339     return new MappedStatement.Builder(config, "insertAuthor", new StaticSqlSource(config,
340         "INSERT INTO author (id,username,password,email,bio) values(99,'someone','******','someone@apache.org',null)"),
341         SqlCommandType.INSERT)
342             .statementType(StatementType.STATEMENT)
343             .parameterMap(
344                 new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<>()).build())
345             .cache(authorCache).build();
346   }
347 
348   static MappedStatement createSelectAuthorWithIDof99MappedStatement(final Configuration config) {
349     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
350     return new MappedStatement.Builder(config, "selectAuthor",
351         new StaticSqlSource(config, "SELECT * FROM author WHERE id = 99"), SqlCommandType.SELECT)
352             .statementType(StatementType.STATEMENT)
353             .parameterMap(
354                 new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<>()).build())
355             .resultMaps(new ArrayList<ResultMap>() {
356               private static final long serialVersionUID = 1L;
357               {
358                 add(new ResultMap.Builder(config, "defaultResultMap", Author.class, new ArrayList<ResultMapping>() {
359                   private static final long serialVersionUID = 1L;
360                   {
361                     add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class)).build());
362                     add(new ResultMapping.Builder(config, "username", "username", registry.getTypeHandler(String.class))
363                         .build());
364                     add(new ResultMapping.Builder(config, "password", "password", registry.getTypeHandler(String.class))
365                         .build());
366                     add(new ResultMapping.Builder(config, "email", "email", registry.getTypeHandler(String.class))
367                         .build());
368                     add(new ResultMapping.Builder(config, "bio", "bio", registry.getTypeHandler(String.class)).build());
369                   }
370                 }).build());
371               }
372             }).build();
373   }
374 
375   static MappedStatement prepareComplexSelectBlogMappedStatement(final Configuration config) {
376     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
377     final SqlSource sqlSource = new StaticSqlSource(config, """
378         SELECT b.id \
379              , b.author_id \
380              , b.title \
381              , a.username \
382              , a.password \
383              , a.email \
384              , a.bio\
385           FROM blog b\
386          INNER JOIN author a ON b.author_id = a.id\
387          WHERE b.id = ?\
388         """);
389     final ParameterMap parameterMap = new ParameterMap.Builder(config, "defaultParameterMap", int.class,
390         new ArrayList<ParameterMapping>() {
391           private static final long serialVersionUID = 1L;
392           {
393             add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
394           }
395         }).build();
396     final ResultMap resultMap = new ResultMap.Builder(config, "defaultResultMap", Blog.class,
397         new ArrayList<ResultMapping>() {
398           private static final long serialVersionUID = 1L;
399           {
400             add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class))
401                 .flags(new ArrayList<ResultFlag>() {
402                   private static final long serialVersionUID = 1L;
403                   {
404                     add(ResultFlag.ID);
405                   }
406                 }).build());
407             add(new ResultMapping.Builder(config, "title", "title", registry.getTypeHandler(String.class)).build());
408             add(new ResultMapping.Builder(config, "author.id", "author_id", registry.getTypeHandler(int.class))
409                 .build());
410             add(new ResultMapping.Builder(config, "author.username", "username", registry.getTypeHandler(String.class))
411                 .build());
412             add(new ResultMapping.Builder(config, "author.password", "password", registry.getTypeHandler(String.class))
413                 .build());
414             add(new ResultMapping.Builder(config, "author.email", "email", registry.getTypeHandler(String.class))
415                 .build());
416             add(new ResultMapping.Builder(config, "author.bio", "bio", registry.getTypeHandler(String.class)).build());
417             add(new ResultMapping.Builder(config, "posts", "id", registry.getTypeHandler(int.class))
418                 .javaType(List.class).nestedQueryId("selectPostsForBlog").build());
419           }
420         }).build();
421 
422     return new MappedStatement.Builder(config, "selectBlogById", sqlSource, SqlCommandType.SELECT)
423         .parameterMap(parameterMap).resultMaps(new ArrayList<ResultMap>() {
424           private static final long serialVersionUID = 1L;
425           {
426             add(resultMap);
427           }
428         }).build();
429   }
430 
431   static MappedStatement prepareSelectBlogByIdAndAuthor(final Configuration config) {
432     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
433     final SqlSource sqlSource = new StaticSqlSource(config, """
434         SELECT b.id\
435              , b.author_id\
436              , b.title\
437              , a.username\
438              , a.password\
439              , a.email\
440              , a.bio\
441           FROM blog b\
442          INNER JOIN author a ON b.author_id = a.id\
443          WHERE b.id = ? and a.id = ?\
444          """);
445     final ParameterMap parameterMap = new ParameterMap.Builder(config, "defaultParameterMap", Map.class,
446         new ArrayList<ParameterMapping>() {
447           private static final long serialVersionUID = 1L;
448           {
449             add(new ParameterMapping.Builder(config, "blogId", registry.getTypeHandler(int.class)).build());
450             add(new ParameterMapping.Builder(config, "authorId", registry.getTypeHandler(int.class)).build());
451           }
452         }).build();
453     final ResultMap resultMap = new ResultMap.Builder(config, "defaultResultMap", Blog.class,
454         new ArrayList<ResultMapping>() {
455           private static final long serialVersionUID = 1L;
456           {
457             add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class))
458                 .flags(new ArrayList<ResultFlag>() {
459                   private static final long serialVersionUID = 1L;
460                   {
461                     add(ResultFlag.ID);
462                   }
463                 }).build());
464             add(new ResultMapping.Builder(config, "title", "title", registry.getTypeHandler(String.class)).build());
465             add(new ResultMapping.Builder(config, "author.id", "author_id", registry.getTypeHandler(int.class))
466                 .build());
467             add(new ResultMapping.Builder(config, "author.username", "username", registry.getTypeHandler(String.class))
468                 .build());
469             add(new ResultMapping.Builder(config, "author.password", "password", registry.getTypeHandler(String.class))
470                 .build());
471             add(new ResultMapping.Builder(config, "author.email", "email", registry.getTypeHandler(String.class))
472                 .build());
473             add(new ResultMapping.Builder(config, "author.bio", "bio", registry.getTypeHandler(String.class)).build());
474             add(new ResultMapping.Builder(config, "posts", "id", registry.getTypeHandler(int.class))
475                 .javaType(List.class).nestedQueryId("selectPostsForBlog").build());
476           }
477         }).build();
478 
479     return new MappedStatement.Builder(config, "selectBlogByIdAndAuthor", sqlSource, SqlCommandType.SELECT)
480         .parameterMap(parameterMap).resultMaps(new ArrayList<ResultMap>() {
481           private static final long serialVersionUID = 1L;
482           {
483             add(resultMap);
484           }
485         }).build();
486 
487   }
488 
489   static MappedStatement prepareSelectPostsForBlogMappedStatement(final Configuration config) {
490     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
491     final SqlSource sqlSource = new StaticSqlSource(config, """
492         SELECT p.id\
493              , p.created_on\
494              , p.blog_id\
495              , p.section\
496              , p.subject\
497              , p.body\
498              , pt.tag_id\
499              , t.name as tag_name\
500              , c.id as comment_id\
501              , c.name as comment_name\
502              , c.comment\
503           FROM post p\
504          INNER JOIN post_tag pt ON pt.post_id = p.id\
505          INNER JOIN tag t ON pt.tag_id = t.id\
506          LEFT OUTER JOIN comment c ON c.post_id = p.id\
507          WHERE p.blog_id = ?\
508         """);
509     final ParameterMap parameterMap = new ParameterMap.Builder(config, "defaultParameterMap", Author.class,
510         new ArrayList<ParameterMapping>() {
511           private static final long serialVersionUID = 1L;
512           {
513             add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
514           }
515         }).build();
516     final ResultMap tagResultMap = new ResultMap.Builder(config, "tagResultMap", Tag.class,
517         new ArrayList<ResultMapping>() {
518           private static final long serialVersionUID = 1L;
519           {
520             add(new ResultMapping.Builder(config, "id", "tag_id", registry.getTypeHandler(int.class))
521                 .flags(new ArrayList<ResultFlag>() {
522                   private static final long serialVersionUID = 1L;
523                   {
524                     add(ResultFlag.ID);
525                   }
526                 }).build());
527             add(new ResultMapping.Builder(config, "name", "tag_name", registry.getTypeHandler(String.class)).build());
528           }
529         }).build();
530     final ResultMap commentResultMap = new ResultMap.Builder(config, "commentResultMap", Comment.class,
531         new ArrayList<ResultMapping>() {
532           private static final long serialVersionUID = 1L;
533           {
534             add(new ResultMapping.Builder(config, "id", "comment_id", registry.getTypeHandler(int.class))
535                 .flags(new ArrayList<ResultFlag>() {
536                   private static final long serialVersionUID = 1L;
537                   {
538                     add(ResultFlag.ID);
539                   }
540                 }).build());
541             add(new ResultMapping.Builder(config, "name", "comment_name", registry.getTypeHandler(String.class))
542                 .build());
543             add(new ResultMapping.Builder(config, "comment", "comment", registry.getTypeHandler(String.class)).build());
544           }
545         }).build();
546     config.addResultMap(tagResultMap);
547     config.addResultMap(commentResultMap);
548     final ResultMap postResultMap = new ResultMap.Builder(config, "defaultResultMap", Post.class,
549         new ArrayList<ResultMapping>() {
550           private static final long serialVersionUID = 1L;
551           {
552             add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class))
553                 .flags(new ArrayList<ResultFlag>() {
554                   private static final long serialVersionUID = 1L;
555                   {
556                     add(ResultFlag.ID);
557                   }
558                 }).build());
559             add(new ResultMapping.Builder(config, "blog", "blog_id", registry.getTypeHandler(int.class))
560                 .javaType(Blog.class).nestedQueryId("selectBlogById").build());
561             add(new ResultMapping.Builder(config, "createdOn", "created_on", registry.getTypeHandler(Date.class))
562                 .build());
563             add(new ResultMapping.Builder(config, "section", "section", registry.getTypeHandler(Section.class))
564                 .build());
565             add(new ResultMapping.Builder(config, "subject", "subject", registry.getTypeHandler(String.class)).build());
566             add(new ResultMapping.Builder(config, "body", "body", registry.getTypeHandler(String.class)).build());
567             add(new ResultMapping.Builder(config, "tags").nestedResultMapId(tagResultMap.getId()).build());
568             add(new ResultMapping.Builder(config, "comments").nestedResultMapId(commentResultMap.getId()).build());
569           }
570         }).build();
571     return new MappedStatement.Builder(config, "selectPostsForBlog", sqlSource, SqlCommandType.SELECT)
572         .parameterMap(parameterMap).resultMaps(new ArrayList<ResultMap>() {
573           private static final long serialVersionUID = 1L;
574           {
575             add(postResultMap);
576           }
577         }).build();
578   }
579 
580   static MappedStatement prepareSelectPostMappedStatement(final Configuration config) {
581     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
582     final SqlSource sqlSource = new StaticSqlSource(config, """
583         SELECT p.id\
584              , p.created_on\
585              , p.blog_id\
586              , p.section\
587              , p.subject\
588              , p.body\
589              , pt.tag_id\
590              , t.name as tag_name\
591              , c.id as comment_id\
592              , c.name as comment_name\
593              , c.comment\
594           FROM post p\
595           LEFT OUTER JOIN post_tag pt ON pt.post_id = p.id\
596           LEFT OUTER JOIN tag t ON pt.tag_id = t.id\
597           LEFT OUTER JOIN comment c ON c.post_id = p.id\
598          WHERE p.id = ?\
599          """);
600     final ParameterMap parameterMap = new ParameterMap.Builder(config, "defaultParameterMap", Author.class,
601         new ArrayList<ParameterMapping>() {
602           private static final long serialVersionUID = 1L;
603           {
604             add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
605           }
606         }).build();
607     final ResultMap tagResultMap = new ResultMap.Builder(config, "tagResultMap", Tag.class,
608         new ArrayList<ResultMapping>() {
609           private static final long serialVersionUID = 1L;
610           {
611             add(new ResultMapping.Builder(config, "id", "tag_id", registry.getTypeHandler(int.class))
612                 .flags(new ArrayList<ResultFlag>() {
613                   private static final long serialVersionUID = 1L;
614                   {
615                     add(ResultFlag.ID);
616                   }
617                 }).build());
618             add(new ResultMapping.Builder(config, "name", "tag_name", registry.getTypeHandler(String.class)).build());
619           }
620         }).build();
621     final ResultMap commentResultMap = new ResultMap.Builder(config, "commentResultMap", Comment.class,
622         new ArrayList<ResultMapping>() {
623           private static final long serialVersionUID = 1L;
624           {
625             add(new ResultMapping.Builder(config, "id", "comment_id", registry.getTypeHandler(int.class))
626                 .flags(new ArrayList<ResultFlag>() {
627                   private static final long serialVersionUID = 1L;
628                   {
629                     add(ResultFlag.ID);
630                   }
631                 }).build());
632             add(new ResultMapping.Builder(config, "name", "comment_name", registry.getTypeHandler(String.class))
633                 .build());
634             add(new ResultMapping.Builder(config, "comment", "comment", registry.getTypeHandler(String.class)).build());
635           }
636         }).build();
637     config.addResultMap(tagResultMap);
638     config.addResultMap(commentResultMap);
639     final ResultMap postResultMap = new ResultMap.Builder(config, "", Post.class, new ArrayList<ResultMapping>() {
640       private static final long serialVersionUID = 1L;
641       {
642         add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class))
643             .flags(new ArrayList<ResultFlag>() {
644               private static final long serialVersionUID = 1L;
645               {
646                 add(ResultFlag.ID);
647               }
648             }).build());
649         add(new ResultMapping.Builder(config, "blog", "blog_id", registry.getTypeHandler(int.class))
650             .javaType(Blog.class).nestedQueryId("selectBlogById").build());
651         add(new ResultMapping.Builder(config, "createdOn", "created_on", registry.getTypeHandler(Date.class)).build());
652         add(new ResultMapping.Builder(config, "section", "section", registry.getTypeHandler(Section.class)).build());
653         add(new ResultMapping.Builder(config, "subject", "subject", registry.getTypeHandler(String.class)).build());
654         add(new ResultMapping.Builder(config, "body", "body", registry.getTypeHandler(String.class)).build());
655         add(new ResultMapping.Builder(config, "tags").nestedResultMapId(tagResultMap.getId()).build());
656         add(new ResultMapping.Builder(config, "comments").nestedResultMapId(commentResultMap.getId()).build());
657       }
658     }).build();
659 
660     return new MappedStatement.Builder(config, "selectPostsForBlog", sqlSource, SqlCommandType.SELECT)
661         .parameterMap(parameterMap).resultMaps(new ArrayList<ResultMap>() {
662           private static final long serialVersionUID = 1L;
663           {
664             add(postResultMap);
665           }
666         }).build();
667   }
668 
669   static MappedStatement prepareSelectPostWithBlogByAuthorMappedStatement(final Configuration config) {
670     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
671     final SqlSource sqlSource = new StaticSqlSource(config, """
672         SELECT p.id\
673              , p.created_on\
674              , p.blog_id\
675              , p.author_id\
676              , p.section\
677              , p.subject\
678              , p.body\
679              , pt.tag_id\
680              , t.name as tag_name\
681              , c.id as comment_id\
682              , c.name as comment_name\
683              , c.comment\
684           FROM post p\
685           LEFT OUTER JOIN post_tag pt ON pt.post_id = p.id\
686           LEFT OUTER JOIN tag t ON pt.tag_id = t.id\
687           LEFT OUTER JOIN comment c ON c.post_id = p.id\
688          WHERE p.id = ?\
689          """);
690     final ParameterMap parameterMap = new ParameterMap.Builder(config, "defaultParameterMap", Author.class,
691         new ArrayList<ParameterMapping>() {
692           private static final long serialVersionUID = 1L;
693           {
694             add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
695           }
696         }).build();
697     final ResultMap tagResultMap = new ResultMap.Builder(config, "tagResultMap", Tag.class,
698         new ArrayList<ResultMapping>() {
699           private static final long serialVersionUID = 1L;
700           {
701             add(new ResultMapping.Builder(config, "id", "tag_id", registry.getTypeHandler(int.class))
702                 .flags(new ArrayList<ResultFlag>() {
703                   private static final long serialVersionUID = 1L;
704                   {
705                     add(ResultFlag.ID);
706                   }
707                 }).build());
708             add(new ResultMapping.Builder(config, "name", "tag_name", registry.getTypeHandler(String.class)).build());
709           }
710         }).build();
711     final ResultMap commentResultMap = new ResultMap.Builder(config, "commentResultMap", Comment.class,
712         new ArrayList<ResultMapping>() {
713           private static final long serialVersionUID = 1L;
714           {
715             add(new ResultMapping.Builder(config, "id", "comment_id", registry.getTypeHandler(int.class))
716                 .flags(new ArrayList<ResultFlag>() {
717                   private static final long serialVersionUID = 1L;
718                   {
719                     add(ResultFlag.ID);
720                   }
721                 }).build());
722             add(new ResultMapping.Builder(config, "name", "comment_name", registry.getTypeHandler(String.class))
723                 .build());
724             add(new ResultMapping.Builder(config, "comment", "comment", registry.getTypeHandler(String.class)).build());
725           }
726         }).build();
727     config.addResultMap(tagResultMap);
728     config.addResultMap(commentResultMap);
729     final ResultMap postResultMap = new ResultMap.Builder(config, "postResultMap", Post.class,
730         new ArrayList<ResultMapping>() {
731           private static final long serialVersionUID = 1L;
732           {
733             add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class))
734                 .flags(new ArrayList<ResultFlag>() {
735                   private static final long serialVersionUID = 1L;
736                   {
737                     add(ResultFlag.ID);
738                   }
739                 }).build());
740 
741             add(new ResultMapping.Builder(config, "blog").nestedQueryId("selectBlogByIdAndAuthor")
742                 .composites(new ArrayList<ResultMapping>() {
743                   private static final long serialVersionUID = 1L;
744                   {
745                     add(new ResultMapping.Builder(config, "authorId", "author_id", registry.getTypeHandler(int.class))
746                         .build());
747                     add(new ResultMapping.Builder(config, "blogId", "blog_id", registry.getTypeHandler(int.class))
748                         .build());
749                   }
750                 }).build());
751             add(new ResultMapping.Builder(config, "createdOn", "created_on", registry.getTypeHandler(Date.class))
752                 .build());
753             add(new ResultMapping.Builder(config, "section", "section", registry.getTypeHandler(Section.class))
754                 .build());
755             add(new ResultMapping.Builder(config, "subject", "subject", registry.getTypeHandler(String.class)).build());
756             add(new ResultMapping.Builder(config, "body", "body", registry.getTypeHandler(String.class)).build());
757             add(new ResultMapping.Builder(config, "tags").nestedResultMapId(tagResultMap.getId()).build());
758             add(new ResultMapping.Builder(config, "comments").nestedResultMapId(commentResultMap.getId()).build());
759           }
760         }).build();
761 
762     return new MappedStatement.Builder(config, "selectPostsForBlog", sqlSource, SqlCommandType.SELECT)
763         .parameterMap(parameterMap).resultMaps(new ArrayList<ResultMap>() {
764           private static final long serialVersionUID = 1L;
765           {
766             add(postResultMap);
767           }
768         }).build();
769   }
770 
771   static MappedStatement prepareInsertAuthorMappedStatementWithBeforeAutoKey(final Configuration config) {
772     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
773     final ResultMap rm = new ResultMap.Builder(config, "keyResultMap", Integer.class, new ArrayList<>()).build();
774 
775     MappedStatement kms = new MappedStatement.Builder(config, "insertAuthor!selectKey",
776         new StaticSqlSource(config, "SELECT 123456 as id FROM SYSIBM.SYSDUMMY1"), SqlCommandType.SELECT)
777             .keyProperty("id").resultMaps(new ArrayList<ResultMap>() {
778               private static final long serialVersionUID = 1L;
779               {
780                 add(rm);
781               }
782             }).build();
783     config.addMappedStatement(kms);
784     return new MappedStatement.Builder(config, "insertAuthor", new DynamicSqlSource(config, new TextSqlNode(
785         "INSERT INTO author (id,username,password,email,bio,favourite_section) values(#{id},#{username},#{password},#{email},#{bio:VARCHAR},#{favouriteSection})")),
786         SqlCommandType.INSERT).parameterMap(
787             new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<ParameterMapping>() {
788               private static final long serialVersionUID = 1L;
789               {
790                 add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(Integer.class)).build());
791                 add(new ParameterMapping.Builder(config, "username", registry.getTypeHandler(String.class)).build());
792                 add(new ParameterMapping.Builder(config, "password", registry.getTypeHandler(String.class)).build());
793                 add(new ParameterMapping.Builder(config, "email", registry.getTypeHandler(String.class)).build());
794                 add(new ParameterMapping.Builder(config, "bio", registry.getTypeHandler(String.class))
795                     .jdbcType(JdbcType.VARCHAR).build());
796                 add(new ParameterMapping.Builder(config, "favouriteSection", registry.getTypeHandler(Section.class))
797                     .jdbcType(JdbcType.VARCHAR).build());
798               }
799             }).build()).cache(authorCache).keyGenerator(new SelectKeyGenerator(kms, true)).keyProperty("id").build();
800   }
801 
802   private ExecutorTestHelper() {
803   }
804 
805 }