View Javadoc
1   /**
2    *    Copyright 2009-2020 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    *       http://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.binding;
17  
18  import static com.googlecode.catchexception.apis.BDDCatchException.*;
19  import static org.assertj.core.api.BDDAssertions.then;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import java.io.IOException;
23  import java.lang.reflect.Method;
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.HashMap;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Map;
31  
32  import javassist.util.proxy.Proxy;
33  
34  import javax.sql.DataSource;
35  
36  import net.sf.cglib.proxy.Factory;
37  
38  import org.apache.ibatis.BaseDataTest;
39  import org.apache.ibatis.binding.MapperProxy.MapperMethodInvoker;
40  import org.apache.ibatis.builder.BuilderException;
41  import org.apache.ibatis.cursor.Cursor;
42  import org.apache.ibatis.domain.blog.Author;
43  import org.apache.ibatis.domain.blog.Blog;
44  import org.apache.ibatis.domain.blog.DraftPost;
45  import org.apache.ibatis.domain.blog.Post;
46  import org.apache.ibatis.domain.blog.Section;
47  import org.apache.ibatis.exceptions.PersistenceException;
48  import org.apache.ibatis.executor.result.DefaultResultHandler;
49  import org.apache.ibatis.mapping.Environment;
50  import org.apache.ibatis.session.Configuration;
51  import org.apache.ibatis.session.RowBounds;
52  import org.apache.ibatis.session.SqlSession;
53  import org.apache.ibatis.session.SqlSessionFactory;
54  import org.apache.ibatis.session.SqlSessionFactoryBuilder;
55  import org.apache.ibatis.transaction.TransactionFactory;
56  import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
57  import org.junit.jupiter.api.Assertions;
58  import org.junit.jupiter.api.BeforeAll;
59  import org.junit.jupiter.api.Disabled;
60  import org.junit.jupiter.api.Test;
61  
62  class BindingTest {
63    private static SqlSessionFactory sqlSessionFactory;
64  
65    @BeforeAll
66    static void setup() throws Exception {
67      DataSource dataSource = BaseDataTest.createBlogDataSource();
68      BaseDataTest.runScript(dataSource, BaseDataTest.BLOG_DDL);
69      BaseDataTest.runScript(dataSource, BaseDataTest.BLOG_DATA);
70      TransactionFactory transactionFactory = new JdbcTransactionFactory();
71      Environment environment = new Environment("Production", transactionFactory, dataSource);
72      Configuration configuration = new Configuration(environment);
73      configuration.setLazyLoadingEnabled(true);
74      configuration.setUseActualParamName(false); // to test legacy style reference (#{0} #{1})
75      configuration.getTypeAliasRegistry().registerAlias(Blog.class);
76      configuration.getTypeAliasRegistry().registerAlias(Post.class);
77      configuration.getTypeAliasRegistry().registerAlias(Author.class);
78      configuration.addMapper(BoundBlogMapper.class);
79      configuration.addMapper(BoundAuthorMapper.class);
80      sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
81    }
82  
83    @Test
84    void shouldSelectBlogWithPostsUsingSubSelect() {
85      try (SqlSession session = sqlSessionFactory.openSession()) {
86        BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
87        Blog b = mapper.selectBlogWithPostsUsingSubSelect(1);
88        assertEquals(1, b.getId());
89        assertNotNull(b.getAuthor());
90        assertEquals(101, b.getAuthor().getId());
91        assertEquals("jim", b.getAuthor().getUsername());
92        assertEquals("********", b.getAuthor().getPassword());
93        assertEquals(2, b.getPosts().size());
94      }
95    }
96  
97    @Test
98    void shouldFindPostsInList() {
99      try (SqlSession session = sqlSessionFactory.openSession()) {
100       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
101       List<Post> posts = mapper.findPostsInList(new ArrayList<Integer>() {{
102         add(1);
103         add(3);
104         add(5);
105       }});
106       assertEquals(3, posts.size());
107       session.rollback();
108     }
109   }
110 
111   @Test
112   void shouldFindPostsInArray() {
113     try (SqlSession session = sqlSessionFactory.openSession()) {
114       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
115       Integer[] params = new Integer[]{1, 3, 5};
116       List<Post> posts = mapper.findPostsInArray(params);
117       assertEquals(3, posts.size());
118       session.rollback();
119     }
120   }
121 
122   @Test
123   void shouldFindThreeSpecificPosts() {
124     try (SqlSession session = sqlSessionFactory.openSession()) {
125       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
126       List<Post> posts = mapper.findThreeSpecificPosts(1, new RowBounds(1, 1), 3, 5);
127       assertEquals(1, posts.size());
128       assertEquals(3, posts.get(0).getId());
129       session.rollback();
130     }
131   }
132 
133   @Test
134   void shouldInsertAuthorWithSelectKey() {
135     try (SqlSession session = sqlSessionFactory.openSession()) {
136       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
137       Authorg/Author.html#Author">Author author = new Author(-1, "cbegin", "******", "cbegin@nowhere.com", "N/A", Section.NEWS);
138       int rows = mapper.insertAuthor(author);
139       assertEquals(1, rows);
140       session.rollback();
141     }
142   }
143 
144   @Test
145   void verifyErrorMessageFromSelectKey() {
146     try (SqlSession session = sqlSessionFactory.openSession()) {
147       try {
148         BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
149         Authorg/Author.html#Author">Author author = new Author(-1, "cbegin", "******", "cbegin@nowhere.com", "N/A", Section.NEWS);
150         when(() -> mapper.insertAuthorInvalidSelectKey(author));
151         then(caughtException()).isInstanceOf(PersistenceException.class).hasMessageContaining(
152             "### The error may exist in org/apache/ibatis/binding/BoundAuthorMapper.xml" + System.lineSeparator() +
153                 "### The error may involve org.apache.ibatis.binding.BoundAuthorMapper.insertAuthorInvalidSelectKey!selectKey" + System.lineSeparator() +
154                 "### The error occurred while executing a query");
155       } finally {
156         session.rollback();
157       }
158     }
159   }
160 
161   @Test
162   void verifyErrorMessageFromInsertAfterSelectKey() {
163     try (SqlSession session = sqlSessionFactory.openSession()) {
164       try {
165         BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
166         Authorg/Author.html#Author">Author author = new Author(-1, "cbegin", "******", "cbegin@nowhere.com", "N/A", Section.NEWS);
167         when(() -> mapper.insertAuthorInvalidInsert(author));
168         then(caughtException()).isInstanceOf(PersistenceException.class).hasMessageContaining(
169             "### The error may exist in org/apache/ibatis/binding/BoundAuthorMapper.xml" + System.lineSeparator() +
170                 "### The error may involve org.apache.ibatis.binding.BoundAuthorMapper.insertAuthorInvalidInsert" + System.lineSeparator() +
171                 "### The error occurred while executing an update");
172       } finally {
173         session.rollback();
174       }
175     }
176   }
177 
178   @Test
179   void shouldInsertAuthorWithSelectKeyAndDynamicParams() {
180     try (SqlSession session = sqlSessionFactory.openSession()) {
181       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
182       Authorg/Author.html#Author">Author author = new Author(-1, "cbegin", "******", "cbegin@nowhere.com", "N/A", Section.NEWS);
183       int rows = mapper.insertAuthorDynamic(author);
184       assertEquals(1, rows);
185       assertNotEquals(-1, author.getId()); // id must be autogenerated
186       Author author2 = mapper.selectAuthor(author.getId());
187       assertNotNull(author2);
188       assertEquals(author.getEmail(), author2.getEmail());
189       session.rollback();
190     }
191   }
192 
193   @Test
194   void shouldSelectRandom() {
195     try (SqlSession session = sqlSessionFactory.openSession()) {
196       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
197       Integer x = mapper.selectRandom();
198       assertNotNull(x);
199     }
200   }
201 
202   @Test
203   void shouldExecuteBoundSelectListOfBlogsStatement() {
204     try (SqlSession session = sqlSessionFactory.openSession()) {
205       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
206       List<Blog> blogs = mapper.selectBlogs();
207       assertEquals(2, blogs.size());
208     }
209   }
210 
211   @Test
212   void shouldExecuteBoundSelectMapOfBlogsById() {
213     try (SqlSession session = sqlSessionFactory.openSession()) {
214       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
215       Map<Integer,Blog> blogs = mapper.selectBlogsAsMapById();
216       assertEquals(2, blogs.size());
217       for(Map.Entry<Integer,Blog> blogEntry : blogs.entrySet()) {
218         assertEquals(blogEntry.getKey(), (Integer) blogEntry.getValue().getId());
219       }
220     }
221   }
222 
223   @Test
224   void shouldExecuteMultipleBoundSelectOfBlogsByIdInWithProvidedResultHandlerBetweenSessions() {
225     final DefaultResultHandler handler = new DefaultResultHandler();
226     try (SqlSession session = sqlSessionFactory.openSession()) {
227       session.select("selectBlogsAsMapById", handler);
228     }
229 
230     final DefaultResultHandler moreHandler = new DefaultResultHandler();
231     try (SqlSession session = sqlSessionFactory.openSession()) {
232       session.select("selectBlogsAsMapById", moreHandler);
233     }
234     assertEquals(2, handler.getResultList().size());
235     assertEquals(2, moreHandler.getResultList().size());
236   }
237 
238   @Test
239   void shouldExecuteMultipleBoundSelectOfBlogsByIdInWithProvidedResultHandlerInSameSession() {
240     try (SqlSession session = sqlSessionFactory.openSession()) {
241       final DefaultResultHandler handler = new DefaultResultHandler();
242       session.select("selectBlogsAsMapById", handler);
243 
244       final DefaultResultHandler moreHandler = new DefaultResultHandler();
245       session.select("selectBlogsAsMapById", moreHandler);
246 
247       assertEquals(2, handler.getResultList().size());
248       assertEquals(2, moreHandler.getResultList().size());
249     }
250   }
251 
252   @Test
253   void shouldExecuteMultipleBoundSelectMapOfBlogsByIdInSameSessionWithoutClearingLocalCache() {
254     try (SqlSession session = sqlSessionFactory.openSession()) {
255       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
256       Map<Integer,Blog> blogs = mapper.selectBlogsAsMapById();
257       Map<Integer,Blog> moreBlogs = mapper.selectBlogsAsMapById();
258       assertEquals(2, blogs.size());
259       assertEquals(2, moreBlogs.size());
260       for(Map.Entry<Integer,Blog> blogEntry : blogs.entrySet()) {
261         assertEquals(blogEntry.getKey(), (Integer) blogEntry.getValue().getId());
262       }
263       for(Map.Entry<Integer,Blog> blogEntry : moreBlogs.entrySet()) {
264         assertEquals(blogEntry.getKey(), (Integer) blogEntry.getValue().getId());
265       }
266     }
267   }
268 
269   @Test
270   void shouldExecuteMultipleBoundSelectMapOfBlogsByIdBetweenTwoSessionsWithGlobalCacheEnabled() {
271     Map<Integer,Blog> blogs;
272     try (SqlSession session = sqlSessionFactory.openSession()) {
273       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
274       blogs = mapper.selectBlogsAsMapById();
275     }
276     try (SqlSession session = sqlSessionFactory.openSession()) {
277       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
278       Map<Integer,Blog> moreBlogs = mapper.selectBlogsAsMapById();
279       assertEquals(2, blogs.size());
280       assertEquals(2, moreBlogs.size());
281       for(Map.Entry<Integer,Blog> blogEntry : blogs.entrySet()) {
282         assertEquals(blogEntry.getKey(), (Integer) blogEntry.getValue().getId());
283       }
284       for(Map.Entry<Integer,Blog> blogEntry : moreBlogs.entrySet()) {
285         assertEquals(blogEntry.getKey(), (Integer) blogEntry.getValue().getId());
286       }
287     }
288   }
289 
290   @Test
291   void shouldSelectListOfBlogsUsingXMLConfig() {
292     try (SqlSession session = sqlSessionFactory.openSession()) {
293       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
294       List<Blog> blogs = mapper.selectBlogsFromXML();
295       assertEquals(2, blogs.size());
296     }
297   }
298 
299   @Test
300   void shouldExecuteBoundSelectListOfBlogsStatementUsingProvider() {
301     try (SqlSession session = sqlSessionFactory.openSession()) {
302       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
303       List<Blog> blogs = mapper.selectBlogsUsingProvider();
304       assertEquals(2, blogs.size());
305     }
306   }
307 
308   @Test
309   void shouldExecuteBoundSelectListOfBlogsAsMaps() {
310     try (SqlSession session = sqlSessionFactory.openSession()) {
311       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
312       List<Map<String,Object>> blogs = mapper.selectBlogsAsMaps();
313       assertEquals(2, blogs.size());
314     }
315   }
316 
317   @Test
318   void shouldSelectListOfPostsLike() {
319     try (SqlSession session = sqlSessionFactory.openSession()) {
320       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
321       List<Post> posts = mapper.selectPostsLike(new RowBounds(1,1),"%a%");
322       assertEquals(1, posts.size());
323     }
324   }
325 
326   @Test
327   void shouldSelectListOfPostsLikeTwoParameters() {
328     try (SqlSession session = sqlSessionFactory.openSession()) {
329       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
330       List<Post> posts = mapper.selectPostsLikeSubjectAndBody(new RowBounds(1,1),"%a%","%a%");
331       assertEquals(1, posts.size());
332     }
333   }
334 
335   @Test
336   void shouldExecuteBoundSelectOneBlogStatement() {
337     try (SqlSession session = sqlSessionFactory.openSession()) {
338       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
339       Blog blog = mapper.selectBlog(1);
340       assertEquals(1, blog.getId());
341       assertEquals("Jim Business", blog.getTitle());
342     }
343   }
344 
345   @Test
346   void shouldExecuteBoundSelectOneBlogStatementWithConstructor() {
347     try (SqlSession session = sqlSessionFactory.openSession()) {
348       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
349       Blog blog = mapper.selectBlogUsingConstructor(1);
350       assertEquals(1, blog.getId());
351       assertEquals("Jim Business", blog.getTitle());
352       assertNotNull(blog.getAuthor(), "author should not be null");
353       List<Post> posts = blog.getPosts();
354       assertTrue(posts != null && !posts.isEmpty(), "posts should not be empty");
355     }
356   }
357 
358   @Test
359   void shouldExecuteBoundSelectBlogUsingConstructorWithResultMap() {
360     try (SqlSession session = sqlSessionFactory.openSession()) {
361       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
362       Blog blog = mapper.selectBlogUsingConstructorWithResultMap(1);
363       assertEquals(1, blog.getId());
364       assertEquals("Jim Business", blog.getTitle());
365       assertNotNull(blog.getAuthor(), "author should not be null");
366       List<Post> posts = blog.getPosts();
367       assertTrue(posts != null && !posts.isEmpty(), "posts should not be empty");
368     }
369   }
370 
371   @Test
372   void shouldExecuteBoundSelectBlogUsingConstructorWithResultMapAndProperties() {
373     try (SqlSession session = sqlSessionFactory.openSession()) {
374       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
375       Blog blog = mapper.selectBlogUsingConstructorWithResultMapAndProperties(1);
376       assertEquals(1, blog.getId());
377       assertEquals("Jim Business", blog.getTitle());
378       assertNotNull(blog.getAuthor(), "author should not be null");
379       Author author = blog.getAuthor();
380       assertEquals(101, author.getId());
381       assertEquals("jim@ibatis.apache.org", author.getEmail());
382       assertEquals("jim", author.getUsername());
383       assertEquals(Section.NEWS, author.getFavouriteSection());
384       List<Post> posts = blog.getPosts();
385       assertNotNull(posts, "posts should not be empty");
386       assertEquals(2, posts.size());
387     }
388   }
389 
390   @Disabled
391   @Test // issue #480 and #101
392   void shouldExecuteBoundSelectBlogUsingConstructorWithResultMapCollection() {
393     try (SqlSession session = sqlSessionFactory.openSession()) {
394       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
395       Blog blog = mapper.selectBlogUsingConstructorWithResultMapCollection(1);
396       assertEquals(1, blog.getId());
397       assertEquals("Jim Business", blog.getTitle());
398       assertNotNull(blog.getAuthor(), "author should not be null");
399       List<Post> posts = blog.getPosts();
400       assertTrue(posts != null && !posts.isEmpty(), "posts should not be empty");
401     }
402   }
403 
404   @Test
405   void shouldExecuteBoundSelectOneBlogStatementWithConstructorUsingXMLConfig() {
406     try (SqlSession session = sqlSessionFactory.openSession()) {
407       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
408       Blog blog = mapper.selectBlogByIdUsingConstructor(1);
409       assertEquals(1, blog.getId());
410       assertEquals("Jim Business", blog.getTitle());
411       assertNotNull(blog.getAuthor(), "author should not be null");
412       List<Post> posts = blog.getPosts();
413       assertTrue(posts != null && !posts.isEmpty(), "posts should not be empty");
414     }
415   }
416 
417   @Test
418   void shouldSelectOneBlogAsMap() {
419     try (SqlSession session = sqlSessionFactory.openSession()) {
420       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
421       Map<String,Object> blog = mapper.selectBlogAsMap(new HashMap<String, Object>() {
422         {
423           put("id", 1);
424         }
425       });
426       assertEquals(1, blog.get("ID"));
427       assertEquals("Jim Business", blog.get("TITLE"));
428     }
429   }
430 
431   @Test
432   void shouldSelectOneAuthor() {
433     try (SqlSession session = sqlSessionFactory.openSession()) {
434       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
435       Author author = mapper.selectAuthor(101);
436       assertEquals(101, author.getId());
437       assertEquals("jim", author.getUsername());
438       assertEquals("********", author.getPassword());
439       assertEquals("jim@ibatis.apache.org", author.getEmail());
440       assertEquals("", author.getBio());
441     }
442   }
443 
444   @Test
445   void shouldSelectOneAuthorFromCache() {
446     Author author1 = selectOneAuthor();
447     Author author2 = selectOneAuthor();
448     assertSame(author1, author2, "Same (cached) instance should be returned unless rollback is called.");
449   }
450 
451   private Author selectOneAuthor() {
452     try (SqlSession session = sqlSessionFactory.openSession()) {
453       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
454       return mapper.selectAuthor(101);
455     }
456   }
457 
458   @Test
459   void shouldSelectOneAuthorByConstructor() {
460     try (SqlSession session = sqlSessionFactory.openSession()) {
461       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
462       Author author = mapper.selectAuthorConstructor(101);
463       assertEquals(101, author.getId());
464       assertEquals("jim", author.getUsername());
465       assertEquals("********", author.getPassword());
466       assertEquals("jim@ibatis.apache.org", author.getEmail());
467       assertEquals("", author.getBio());
468     }
469   }
470 
471   @Test
472   void shouldSelectDraftTypedPosts() {
473     try (SqlSession session = sqlSessionFactory.openSession()) {
474       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
475       List<Post> posts = mapper.selectPosts();
476       assertEquals(5, posts.size());
477       assertTrue(posts.get(0) instanceof DraftPost);
478       assertFalse(posts.get(1) instanceof DraftPost);
479       assertTrue(posts.get(2) instanceof DraftPost);
480       assertFalse(posts.get(3) instanceof DraftPost);
481       assertFalse(posts.get(4) instanceof DraftPost);
482     }
483   }
484 
485   @Test
486   void shouldSelectDraftTypedPostsWithResultMap() {
487     try (SqlSession session = sqlSessionFactory.openSession()) {
488       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
489       List<Post> posts = mapper.selectPostsWithResultMap();
490       assertEquals(5, posts.size());
491       assertTrue(posts.get(0) instanceof DraftPost);
492       assertFalse(posts.get(1) instanceof DraftPost);
493       assertTrue(posts.get(2) instanceof DraftPost);
494       assertFalse(posts.get(3) instanceof DraftPost);
495       assertFalse(posts.get(4) instanceof DraftPost);
496     }
497   }
498 
499   @Test
500   void shouldReturnANotNullToString() {
501     try (SqlSession session = sqlSessionFactory.openSession()) {
502       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
503       assertNotNull(mapper.toString());
504     }
505   }
506 
507   @Test
508   void shouldReturnANotNullHashCode() {
509     try (SqlSession session = sqlSessionFactory.openSession()) {
510       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
511       assertNotNull(mapper.hashCode());
512     }
513   }
514 
515   @Test
516   void shouldCompareTwoMappers() {
517     try (SqlSession session = sqlSessionFactory.openSession()) {
518       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
519       BoundBlogMapper mapper2 = session.getMapper(BoundBlogMapper.class);
520       assertNotEquals(mapper, mapper2);
521     }
522   }
523 
524   @Test
525   void shouldFailWhenSelectingOneBlogWithNonExistentParam() {
526     try (SqlSession session = sqlSessionFactory.openSession()) {
527       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
528       assertThrows(Exception.class, () -> mapper.selectBlogByNonExistentParam(1));
529     }
530   }
531 
532   @Test
533   void shouldFailWhenSelectingOneBlogWithNullParam() {
534     try (SqlSession session = sqlSessionFactory.openSession()) {
535       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
536       assertThrows(Exception.class, () -> mapper.selectBlogByNullParam(null));
537     }
538   }
539 
540   @Test // Decided that maps are dynamic so no existent params do not fail
541   void shouldFailWhenSelectingOneBlogWithNonExistentNestedParam() {
542     try (SqlSession session = sqlSessionFactory.openSession()) {
543       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
544       mapper.selectBlogByNonExistentNestedParam(1, Collections.<String, Object>emptyMap());
545     }
546   }
547 
548   @Test
549   void shouldSelectBlogWithDefault30ParamNames() {
550     try (SqlSession session = sqlSessionFactory.openSession()) {
551       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
552       Blog blog = mapper.selectBlogByDefault30ParamNames(1, "Jim Business");
553       assertNotNull(blog);
554     }
555   }
556 
557   @Test
558   void shouldSelectBlogWithDefault31ParamNames() {
559     try (SqlSession session = sqlSessionFactory.openSession()) {
560       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
561       Blog blog = mapper.selectBlogByDefault31ParamNames(1, "Jim Business");
562       assertNotNull(blog);
563     }
564   }
565 
566   @Test
567   void shouldSelectBlogWithAParamNamedValue() {
568     try (SqlSession session = sqlSessionFactory.openSession()) {
569       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
570       Blog blog = mapper.selectBlogWithAParamNamedValue("id", 1, "Jim Business");
571       assertNotNull(blog);
572     }
573   }
574 
575   @Test
576   void shouldCacheMapperMethod() throws Exception {
577     try (SqlSession session = sqlSessionFactory.openSession()) {
578 
579       // Create another mapper instance with a method cache we can test against:
580       final MapperProxyFactory<BoundBlogMapper> mapperProxyFactory = new MapperProxyFactory<BoundBlogMapper>(BoundBlogMapper.class);
581       assertEquals(BoundBlogMapper.class, mapperProxyFactory.getMapperInterface());
582       final BoundBlogMapper mapper = mapperProxyFactory.newInstance(session);
583       assertNotSame(mapper, mapperProxyFactory.newInstance(session));
584       assertTrue(mapperProxyFactory.getMethodCache().isEmpty());
585 
586       // Mapper methods we will call later:
587       final Method selectBlog = BoundBlogMapper.class.getMethod("selectBlog", Integer.TYPE);
588       final Method selectBlogByIdUsingConstructor = BoundBlogMapper.class.getMethod("selectBlogByIdUsingConstructor", Integer.TYPE);
589 
590       // Call mapper method and verify it is cached:
591       mapper.selectBlog(1);
592       assertEquals(1, mapperProxyFactory.getMethodCache().size());
593       assertTrue(mapperProxyFactory.getMethodCache().containsKey(selectBlog));
594       final MapperMethodInvoker cachedSelectBlog = mapperProxyFactory.getMethodCache().get(selectBlog);
595 
596       // Call mapper method again and verify the cache is unchanged:
597       session.clearCache();
598       mapper.selectBlog(1);
599       assertEquals(1, mapperProxyFactory.getMethodCache().size());
600       assertSame(cachedSelectBlog, mapperProxyFactory.getMethodCache().get(selectBlog));
601 
602       // Call another mapper method and verify that it shows up in the cache as well:
603       session.clearCache();
604       mapper.selectBlogByIdUsingConstructor(1);
605       assertEquals(2, mapperProxyFactory.getMethodCache().size());
606       assertSame(cachedSelectBlog, mapperProxyFactory.getMethodCache().get(selectBlog));
607       assertTrue(mapperProxyFactory.getMethodCache().containsKey(selectBlogByIdUsingConstructor));
608     }
609   }
610 
611   @Test
612   void shouldGetBlogsWithAuthorsAndPosts() {
613     try (SqlSession session = sqlSessionFactory.openSession()) {
614       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
615       List<Blog> blogs = mapper.selectBlogsWithAutorAndPosts();
616       assertEquals(2, blogs.size());
617       assertTrue(blogs.get(0) instanceof Proxy);
618       assertEquals(101, blogs.get(0).getAuthor().getId());
619       assertEquals(1, blogs.get(0).getPosts().size());
620       assertEquals(1, blogs.get(0).getPosts().get(0).getId());
621       assertTrue(blogs.get(1) instanceof Proxy);
622       assertEquals(102, blogs.get(1).getAuthor().getId());
623       assertEquals(1, blogs.get(1).getPosts().size());
624       assertEquals(2, blogs.get(1).getPosts().get(0).getId());
625     }
626   }
627 
628   @Test
629   void shouldGetBlogsWithAuthorsAndPostsEagerly() {
630     try (SqlSession session = sqlSessionFactory.openSession()) {
631       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
632       List<Blog> blogs = mapper.selectBlogsWithAutorAndPostsEagerly();
633       assertEquals(2, blogs.size());
634       assertFalse(blogs.get(0) instanceof Factory);
635       assertEquals(101, blogs.get(0).getAuthor().getId());
636       assertEquals(1, blogs.get(0).getPosts().size());
637       assertEquals(1, blogs.get(0).getPosts().get(0).getId());
638       assertFalse(blogs.get(1) instanceof Factory);
639       assertEquals(102, blogs.get(1).getAuthor().getId());
640       assertEquals(1, blogs.get(1).getPosts().size());
641       assertEquals(2, blogs.get(1).getPosts().get(0).getId());
642     }
643   }
644 
645   @Test
646   void executeWithResultHandlerAndRowBounds() {
647     try (SqlSession session = sqlSessionFactory.openSession()) {
648       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
649       final DefaultResultHandler handler = new DefaultResultHandler();
650       mapper.collectRangeBlogs(handler, new RowBounds(1, 1));
651 
652       assertEquals(1, handler.getResultList().size());
653       Blogef="../../../../org/apache/ibatis/domain/blog/Blog.html#Blog">Blog blog = (Blog) handler.getResultList().get(0);
654       assertEquals(2, blog.getId());
655     }
656   }
657 
658   @Test
659   void executeWithMapKeyAndRowBounds() {
660     try (SqlSession session = sqlSessionFactory.openSession()) {
661       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
662       Map<Integer, Blog> blogs = mapper.selectRangeBlogsAsMapById(new RowBounds(1, 1));
663 
664       assertEquals(1, blogs.size());
665       Blog blog = blogs.get(2);
666       assertEquals(2, blog.getId());
667     }
668   }
669 
670   @Test
671   void executeWithCursorAndRowBounds() {
672     try (SqlSession session = sqlSessionFactory.openSession()) {
673       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
674       try (Cursor<Blog> blogs = mapper.openRangeBlogs(new RowBounds(1, 1)) ) {
675         Iterator<Blog> blogIterator = blogs.iterator();
676         Blog blog = blogIterator.next();
677         assertEquals(2, blog.getId());
678         assertFalse(blogIterator.hasNext());
679       }
680     } catch (IOException e) {
681       Assertions.fail(e.getMessage());
682     }
683   }
684 
685   @Test
686   void registeredMappers() {
687     Collection<Class<?>> mapperClasses = sqlSessionFactory.getConfiguration().getMapperRegistry().getMappers();
688     assertEquals(2, mapperClasses.size());
689     assertTrue(mapperClasses.contains(BoundBlogMapper.class));
690     assertTrue(mapperClasses.contains(BoundAuthorMapper.class));
691   }
692 
693   @Test
694   void shouldMapPropertiesUsingRepeatableAnnotation() {
695     try (SqlSession session = sqlSessionFactory.openSession()) {
696       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
697       Authorg/Author.html#Author">Author author = new Author(-1, "cbegin", "******", "cbegin@nowhere.com", "N/A", Section.NEWS);
698       mapper.insertAuthor(author);
699       Author author2 = mapper.selectAuthorMapToPropertiesUsingRepeatable(author.getId());
700       assertNotNull(author2);
701       assertEquals(author.getId(), author2.getId());
702       assertEquals(author.getUsername(), author2.getUsername());
703       assertEquals(author.getPassword(), author2.getPassword());
704       assertEquals(author.getBio(), author2.getBio());
705       assertEquals(author.getEmail(), author2.getEmail());
706       session.rollback();
707     }
708   }
709 
710   @Test
711   void shouldMapConstructorUsingRepeatableAnnotation() {
712     try (SqlSession session = sqlSessionFactory.openSession()) {
713       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
714       Authorg/Author.html#Author">Author author = new Author(-1, "cbegin", "******", "cbegin@nowhere.com", "N/A", Section.NEWS);
715       mapper.insertAuthor(author);
716       Author author2 = mapper.selectAuthorMapToConstructorUsingRepeatable(author.getId());
717       assertNotNull(author2);
718       assertEquals(author.getId(), author2.getId());
719       assertEquals(author.getUsername(), author2.getUsername());
720       assertEquals(author.getPassword(), author2.getPassword());
721       assertEquals(author.getBio(), author2.getBio());
722       assertEquals(author.getEmail(), author2.getEmail());
723       assertEquals(author.getFavouriteSection(), author2.getFavouriteSection());
724       session.rollback();
725     }
726   }
727 
728   @Test
729   void shouldMapUsingSingleRepeatableAnnotation() {
730     try (SqlSession session = sqlSessionFactory.openSession()) {
731       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
732       Authorg/Author.html#Author">Author author = new Author(-1, "cbegin", "******", "cbegin@nowhere.com", "N/A", Section.NEWS);
733       mapper.insertAuthor(author);
734       Author author2 = mapper.selectAuthorUsingSingleRepeatable(author.getId());
735       assertNotNull(author2);
736       assertEquals(author.getId(), author2.getId());
737       assertEquals(author.getUsername(), author2.getUsername());
738       assertNull(author2.getPassword());
739       assertNull(author2.getBio());
740       assertNull(author2.getEmail());
741       assertNull(author2.getFavouriteSection());
742       session.rollback();
743     }
744   }
745 
746   @Test
747   void shouldMapWhenSpecifyBothArgAndConstructorArgs() {
748     try (SqlSession session = sqlSessionFactory.openSession()) {
749       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
750       Authorg/Author.html#Author">Author author = new Author(-1, "cbegin", "******", "cbegin@nowhere.com", "N/A", Section.NEWS);
751       mapper.insertAuthor(author);
752       Author author2 = mapper.selectAuthorUsingBothArgAndConstructorArgs(author.getId());
753       assertNotNull(author2);
754       assertEquals(author.getId(), author2.getId());
755       assertEquals(author.getUsername(), author2.getUsername());
756       assertEquals(author.getPassword(), author2.getPassword());
757       assertEquals(author.getBio(), author2.getBio());
758       assertEquals(author.getEmail(), author2.getEmail());
759       assertEquals(author.getFavouriteSection(), author2.getFavouriteSection());
760       session.rollback();
761     }
762   }
763 
764   @Test
765   void shouldMapWhenSpecifyBothResultAndResults() {
766     try (SqlSession session = sqlSessionFactory.openSession()) {
767       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
768       Authorg/Author.html#Author">Author author = new Author(-1, "cbegin", "******", "cbegin@nowhere.com", "N/A", Section.NEWS);
769       mapper.insertAuthor(author);
770       Author author2 = mapper.selectAuthorUsingBothResultAndResults(author.getId());
771       assertNotNull(author2);
772       assertEquals(author.getId(), author2.getId());
773       assertEquals(author.getUsername(), author2.getUsername());
774       assertNull(author2.getPassword());
775       assertNull(author2.getBio());
776       assertNull(author2.getEmail());
777       assertNull(author2.getFavouriteSection());
778       session.rollback();
779     }
780   }
781 
782 }
783