View Javadoc
1   /*
2    *    Copyright 2009-2023 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  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, b.author_id, b.title, a.username, a.password, a.email, a.bio" + " FROM blog b"
379             + " INNER JOIN author a ON b.author_id = a.id" + " WHERE b.id = ?");
380     final ParameterMap parameterMap = new ParameterMap.Builder(config, "defaultParameterMap", int.class,
381         new ArrayList<ParameterMapping>() {
382           private static final long serialVersionUID = 1L;
383           {
384             add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
385           }
386         }).build();
387     final ResultMap resultMap = new ResultMap.Builder(config, "defaultResultMap", Blog.class,
388         new ArrayList<ResultMapping>() {
389           private static final long serialVersionUID = 1L;
390           {
391             add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class))
392                 .flags(new ArrayList<ResultFlag>() {
393                   private static final long serialVersionUID = 1L;
394                   {
395                     add(ResultFlag.ID);
396                   }
397                 }).build());
398             add(new ResultMapping.Builder(config, "title", "title", registry.getTypeHandler(String.class)).build());
399             add(new ResultMapping.Builder(config, "author.id", "author_id", registry.getTypeHandler(int.class))
400                 .build());
401             add(new ResultMapping.Builder(config, "author.username", "username", registry.getTypeHandler(String.class))
402                 .build());
403             add(new ResultMapping.Builder(config, "author.password", "password", registry.getTypeHandler(String.class))
404                 .build());
405             add(new ResultMapping.Builder(config, "author.email", "email", registry.getTypeHandler(String.class))
406                 .build());
407             add(new ResultMapping.Builder(config, "author.bio", "bio", registry.getTypeHandler(String.class)).build());
408             add(new ResultMapping.Builder(config, "posts", "id", registry.getTypeHandler(int.class))
409                 .javaType(List.class).nestedQueryId("selectPostsForBlog").build());
410           }
411         }).build();
412 
413     return new MappedStatement.Builder(config, "selectBlogById", sqlSource, SqlCommandType.SELECT)
414         .parameterMap(parameterMap).resultMaps(new ArrayList<ResultMap>() {
415           private static final long serialVersionUID = 1L;
416           {
417             add(resultMap);
418           }
419         }).build();
420   }
421 
422   static MappedStatement prepareSelectBlogByIdAndAuthor(final Configuration config) {
423     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
424     final SqlSource sqlSource = new StaticSqlSource(config,
425         "SELECT b.id, b.author_id, b.title, a.username, a.password, a.email, a.bio" + " FROM blog b"
426             + " INNER JOIN author a ON b.author_id = a.id" + " WHERE b.id = ? and a.id = ?");
427     final ParameterMap parameterMap = new ParameterMap.Builder(config, "defaultParameterMap", Map.class,
428         new ArrayList<ParameterMapping>() {
429           private static final long serialVersionUID = 1L;
430           {
431             add(new ParameterMapping.Builder(config, "blogId", registry.getTypeHandler(int.class)).build());
432             add(new ParameterMapping.Builder(config, "authorId", registry.getTypeHandler(int.class)).build());
433           }
434         }).build();
435     final ResultMap resultMap = new ResultMap.Builder(config, "defaultResultMap", Blog.class,
436         new ArrayList<ResultMapping>() {
437           private static final long serialVersionUID = 1L;
438           {
439             add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class))
440                 .flags(new ArrayList<ResultFlag>() {
441                   private static final long serialVersionUID = 1L;
442                   {
443                     add(ResultFlag.ID);
444                   }
445                 }).build());
446             add(new ResultMapping.Builder(config, "title", "title", registry.getTypeHandler(String.class)).build());
447             add(new ResultMapping.Builder(config, "author.id", "author_id", registry.getTypeHandler(int.class))
448                 .build());
449             add(new ResultMapping.Builder(config, "author.username", "username", registry.getTypeHandler(String.class))
450                 .build());
451             add(new ResultMapping.Builder(config, "author.password", "password", registry.getTypeHandler(String.class))
452                 .build());
453             add(new ResultMapping.Builder(config, "author.email", "email", registry.getTypeHandler(String.class))
454                 .build());
455             add(new ResultMapping.Builder(config, "author.bio", "bio", registry.getTypeHandler(String.class)).build());
456             add(new ResultMapping.Builder(config, "posts", "id", registry.getTypeHandler(int.class))
457                 .javaType(List.class).nestedQueryId("selectPostsForBlog").build());
458           }
459         }).build();
460 
461     return new MappedStatement.Builder(config, "selectBlogByIdAndAuthor", sqlSource, SqlCommandType.SELECT)
462         .parameterMap(parameterMap).resultMaps(new ArrayList<ResultMap>() {
463           private static final long serialVersionUID = 1L;
464           {
465             add(resultMap);
466           }
467         }).build();
468 
469   }
470 
471   static MappedStatement prepareSelectPostsForBlogMappedStatement(final Configuration config) {
472     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
473     final SqlSource sqlSource = new StaticSqlSource(config,
474         "SELECT p.id, p.created_on, p.blog_id, p.section, p.subject, p.body, pt.tag_id,"
475             + " t.name as tag_name, c.id as comment_id, c.name as comment_name, c.comment" + " FROM post p"
476             + " INNER JOIN post_tag pt ON pt.post_id = p.id" + " INNER JOIN tag t ON pt.tag_id = t.id"
477             + " LEFT OUTER JOIN comment c ON c.post_id = p.id" + " WHERE p.blog_id = ?");
478     final ParameterMap parameterMap = new ParameterMap.Builder(config, "defaultParameterMap", Author.class,
479         new ArrayList<ParameterMapping>() {
480           private static final long serialVersionUID = 1L;
481           {
482             add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
483           }
484         }).build();
485     final ResultMap tagResultMap = new ResultMap.Builder(config, "tagResultMap", Tag.class,
486         new ArrayList<ResultMapping>() {
487           private static final long serialVersionUID = 1L;
488           {
489             add(new ResultMapping.Builder(config, "id", "tag_id", registry.getTypeHandler(int.class))
490                 .flags(new ArrayList<ResultFlag>() {
491                   private static final long serialVersionUID = 1L;
492                   {
493                     add(ResultFlag.ID);
494                   }
495                 }).build());
496             add(new ResultMapping.Builder(config, "name", "tag_name", registry.getTypeHandler(String.class)).build());
497           }
498         }).build();
499     final ResultMap commentResultMap = new ResultMap.Builder(config, "commentResultMap", Comment.class,
500         new ArrayList<ResultMapping>() {
501           private static final long serialVersionUID = 1L;
502           {
503             add(new ResultMapping.Builder(config, "id", "comment_id", registry.getTypeHandler(int.class))
504                 .flags(new ArrayList<ResultFlag>() {
505                   private static final long serialVersionUID = 1L;
506                   {
507                     add(ResultFlag.ID);
508                   }
509                 }).build());
510             add(new ResultMapping.Builder(config, "name", "comment_name", registry.getTypeHandler(String.class))
511                 .build());
512             add(new ResultMapping.Builder(config, "comment", "comment", registry.getTypeHandler(String.class)).build());
513           }
514         }).build();
515     config.addResultMap(tagResultMap);
516     config.addResultMap(commentResultMap);
517     final ResultMap postResultMap = new ResultMap.Builder(config, "defaultResultMap", Post.class,
518         new ArrayList<ResultMapping>() {
519           private static final long serialVersionUID = 1L;
520           {
521             add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class))
522                 .flags(new ArrayList<ResultFlag>() {
523                   private static final long serialVersionUID = 1L;
524                   {
525                     add(ResultFlag.ID);
526                   }
527                 }).build());
528             add(new ResultMapping.Builder(config, "blog", "blog_id", registry.getTypeHandler(int.class))
529                 .javaType(Blog.class).nestedQueryId("selectBlogById").build());
530             add(new ResultMapping.Builder(config, "createdOn", "created_on", registry.getTypeHandler(Date.class))
531                 .build());
532             add(new ResultMapping.Builder(config, "section", "section", registry.getTypeHandler(Section.class))
533                 .build());
534             add(new ResultMapping.Builder(config, "subject", "subject", registry.getTypeHandler(String.class)).build());
535             add(new ResultMapping.Builder(config, "body", "body", registry.getTypeHandler(String.class)).build());
536             add(new ResultMapping.Builder(config, "tags").nestedResultMapId(tagResultMap.getId()).build());
537             add(new ResultMapping.Builder(config, "comments").nestedResultMapId(commentResultMap.getId()).build());
538           }
539         }).build();
540     return new MappedStatement.Builder(config, "selectPostsForBlog", sqlSource, SqlCommandType.SELECT)
541         .parameterMap(parameterMap).resultMaps(new ArrayList<ResultMap>() {
542           private static final long serialVersionUID = 1L;
543           {
544             add(postResultMap);
545           }
546         }).build();
547   }
548 
549   static MappedStatement prepareSelectPostMappedStatement(final Configuration config) {
550     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
551     final SqlSource sqlSource = new StaticSqlSource(config,
552         "SELECT p.id, p.created_on, p.blog_id, p.section, p.subject, p.body, pt.tag_id,"
553             + " t.name as tag_name, c.id as comment_id, c.name as comment_name, c.comment" + " FROM post p"
554             + " LEFT OUTER JOIN post_tag pt ON pt.post_id = p.id" + " LEFT OUTER JOIN tag t ON pt.tag_id = t.id"
555             + " LEFT OUTER JOIN comment c ON c.post_id = p.id" + " WHERE p.id = ?");
556     final ParameterMap parameterMap = new ParameterMap.Builder(config, "defaultParameterMap", Author.class,
557         new ArrayList<ParameterMapping>() {
558           private static final long serialVersionUID = 1L;
559           {
560             add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
561           }
562         }).build();
563     final ResultMap tagResultMap = new ResultMap.Builder(config, "tagResultMap", Tag.class,
564         new ArrayList<ResultMapping>() {
565           private static final long serialVersionUID = 1L;
566           {
567             add(new ResultMapping.Builder(config, "id", "tag_id", registry.getTypeHandler(int.class))
568                 .flags(new ArrayList<ResultFlag>() {
569                   private static final long serialVersionUID = 1L;
570                   {
571                     add(ResultFlag.ID);
572                   }
573                 }).build());
574             add(new ResultMapping.Builder(config, "name", "tag_name", registry.getTypeHandler(String.class)).build());
575           }
576         }).build();
577     final ResultMap commentResultMap = new ResultMap.Builder(config, "commentResultMap", Comment.class,
578         new ArrayList<ResultMapping>() {
579           private static final long serialVersionUID = 1L;
580           {
581             add(new ResultMapping.Builder(config, "id", "comment_id", registry.getTypeHandler(int.class))
582                 .flags(new ArrayList<ResultFlag>() {
583                   private static final long serialVersionUID = 1L;
584                   {
585                     add(ResultFlag.ID);
586                   }
587                 }).build());
588             add(new ResultMapping.Builder(config, "name", "comment_name", registry.getTypeHandler(String.class))
589                 .build());
590             add(new ResultMapping.Builder(config, "comment", "comment", registry.getTypeHandler(String.class)).build());
591           }
592         }).build();
593     config.addResultMap(tagResultMap);
594     config.addResultMap(commentResultMap);
595     final ResultMap postResultMap = new ResultMap.Builder(config, "", Post.class, new ArrayList<ResultMapping>() {
596       private static final long serialVersionUID = 1L;
597       {
598         add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class))
599             .flags(new ArrayList<ResultFlag>() {
600               private static final long serialVersionUID = 1L;
601               {
602                 add(ResultFlag.ID);
603               }
604             }).build());
605         add(new ResultMapping.Builder(config, "blog", "blog_id", registry.getTypeHandler(int.class))
606             .javaType(Blog.class).nestedQueryId("selectBlogById").build());
607         add(new ResultMapping.Builder(config, "createdOn", "created_on", registry.getTypeHandler(Date.class)).build());
608         add(new ResultMapping.Builder(config, "section", "section", registry.getTypeHandler(Section.class)).build());
609         add(new ResultMapping.Builder(config, "subject", "subject", registry.getTypeHandler(String.class)).build());
610         add(new ResultMapping.Builder(config, "body", "body", registry.getTypeHandler(String.class)).build());
611         add(new ResultMapping.Builder(config, "tags").nestedResultMapId(tagResultMap.getId()).build());
612         add(new ResultMapping.Builder(config, "comments").nestedResultMapId(commentResultMap.getId()).build());
613       }
614     }).build();
615 
616     return new MappedStatement.Builder(config, "selectPostsForBlog", sqlSource, SqlCommandType.SELECT)
617         .parameterMap(parameterMap).resultMaps(new ArrayList<ResultMap>() {
618           private static final long serialVersionUID = 1L;
619           {
620             add(postResultMap);
621           }
622         }).build();
623   }
624 
625   static MappedStatement prepareSelectPostWithBlogByAuthorMappedStatement(final Configuration config) {
626     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
627     final SqlSource sqlSource = new StaticSqlSource(config,
628         "SELECT p.id, p.created_on, p.blog_id, p.author_id, p.section, p.subject, p.body, pt.tag_id,"
629             + " t.name as tag_name, c.id as comment_id, c.name as comment_name, c.comment" + " FROM post p"
630             + " LEFT OUTER JOIN post_tag pt ON pt.post_id = p.id" + " LEFT OUTER JOIN tag t ON pt.tag_id = t.id"
631             + " LEFT OUTER JOIN comment c ON c.post_id = p.id" + " WHERE p.id = ?");
632     final ParameterMap parameterMap = new ParameterMap.Builder(config, "defaultParameterMap", Author.class,
633         new ArrayList<ParameterMapping>() {
634           private static final long serialVersionUID = 1L;
635           {
636             add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(int.class)).build());
637           }
638         }).build();
639     final ResultMap tagResultMap = new ResultMap.Builder(config, "tagResultMap", Tag.class,
640         new ArrayList<ResultMapping>() {
641           private static final long serialVersionUID = 1L;
642           {
643             add(new ResultMapping.Builder(config, "id", "tag_id", registry.getTypeHandler(int.class))
644                 .flags(new ArrayList<ResultFlag>() {
645                   private static final long serialVersionUID = 1L;
646                   {
647                     add(ResultFlag.ID);
648                   }
649                 }).build());
650             add(new ResultMapping.Builder(config, "name", "tag_name", registry.getTypeHandler(String.class)).build());
651           }
652         }).build();
653     final ResultMap commentResultMap = new ResultMap.Builder(config, "commentResultMap", Comment.class,
654         new ArrayList<ResultMapping>() {
655           private static final long serialVersionUID = 1L;
656           {
657             add(new ResultMapping.Builder(config, "id", "comment_id", registry.getTypeHandler(int.class))
658                 .flags(new ArrayList<ResultFlag>() {
659                   private static final long serialVersionUID = 1L;
660                   {
661                     add(ResultFlag.ID);
662                   }
663                 }).build());
664             add(new ResultMapping.Builder(config, "name", "comment_name", registry.getTypeHandler(String.class))
665                 .build());
666             add(new ResultMapping.Builder(config, "comment", "comment", registry.getTypeHandler(String.class)).build());
667           }
668         }).build();
669     config.addResultMap(tagResultMap);
670     config.addResultMap(commentResultMap);
671     final ResultMap postResultMap = new ResultMap.Builder(config, "postResultMap", Post.class,
672         new ArrayList<ResultMapping>() {
673           private static final long serialVersionUID = 1L;
674           {
675             add(new ResultMapping.Builder(config, "id", "id", registry.getTypeHandler(int.class))
676                 .flags(new ArrayList<ResultFlag>() {
677                   private static final long serialVersionUID = 1L;
678                   {
679                     add(ResultFlag.ID);
680                   }
681                 }).build());
682 
683             add(new ResultMapping.Builder(config, "blog").nestedQueryId("selectBlogByIdAndAuthor")
684                 .composites(new ArrayList<ResultMapping>() {
685                   private static final long serialVersionUID = 1L;
686                   {
687                     add(new ResultMapping.Builder(config, "authorId", "author_id", registry.getTypeHandler(int.class))
688                         .build());
689                     add(new ResultMapping.Builder(config, "blogId", "blog_id", registry.getTypeHandler(int.class))
690                         .build());
691                   }
692                 }).build());
693             add(new ResultMapping.Builder(config, "createdOn", "created_on", registry.getTypeHandler(Date.class))
694                 .build());
695             add(new ResultMapping.Builder(config, "section", "section", registry.getTypeHandler(Section.class))
696                 .build());
697             add(new ResultMapping.Builder(config, "subject", "subject", registry.getTypeHandler(String.class)).build());
698             add(new ResultMapping.Builder(config, "body", "body", registry.getTypeHandler(String.class)).build());
699             add(new ResultMapping.Builder(config, "tags").nestedResultMapId(tagResultMap.getId()).build());
700             add(new ResultMapping.Builder(config, "comments").nestedResultMapId(commentResultMap.getId()).build());
701           }
702         }).build();
703 
704     return new MappedStatement.Builder(config, "selectPostsForBlog", sqlSource, SqlCommandType.SELECT)
705         .parameterMap(parameterMap).resultMaps(new ArrayList<ResultMap>() {
706           private static final long serialVersionUID = 1L;
707           {
708             add(postResultMap);
709           }
710         }).build();
711   }
712 
713   static MappedStatement prepareInsertAuthorMappedStatementWithBeforeAutoKey(final Configuration config) {
714     final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();
715     final ResultMap rm = new ResultMap.Builder(config, "keyResultMap", Integer.class, new ArrayList<>()).build();
716 
717     MappedStatement kms = new MappedStatement.Builder(config, "insertAuthor!selectKey",
718         new StaticSqlSource(config, "SELECT 123456 as id FROM SYSIBM.SYSDUMMY1"), SqlCommandType.SELECT)
719             .keyProperty("id").resultMaps(new ArrayList<ResultMap>() {
720               private static final long serialVersionUID = 1L;
721               {
722                 add(rm);
723               }
724             }).build();
725     config.addMappedStatement(kms);
726     return new MappedStatement.Builder(config, "insertAuthor", new DynamicSqlSource(config, new TextSqlNode(
727         "INSERT INTO author (id,username,password,email,bio,favourite_section) values(#{id},#{username},#{password},#{email},#{bio:VARCHAR},#{favouriteSection})")),
728         SqlCommandType.INSERT).parameterMap(
729             new ParameterMap.Builder(config, "defaultParameterMap", Author.class, new ArrayList<ParameterMapping>() {
730               private static final long serialVersionUID = 1L;
731               {
732                 add(new ParameterMapping.Builder(config, "id", registry.getTypeHandler(Integer.class)).build());
733                 add(new ParameterMapping.Builder(config, "username", registry.getTypeHandler(String.class)).build());
734                 add(new ParameterMapping.Builder(config, "password", registry.getTypeHandler(String.class)).build());
735                 add(new ParameterMapping.Builder(config, "email", registry.getTypeHandler(String.class)).build());
736                 add(new ParameterMapping.Builder(config, "bio", registry.getTypeHandler(String.class))
737                     .jdbcType(JdbcType.VARCHAR).build());
738                 add(new ParameterMapping.Builder(config, "favouriteSection", registry.getTypeHandler(Section.class))
739                     .jdbcType(JdbcType.VARCHAR).build());
740               }
741             }).build()).cache(authorCache).keyGenerator(new SelectKeyGenerator(kms, true)).keyProperty("id").build();
742   }
743 
744   private ExecutorTestHelper() {
745   }
746 
747 }