View Javadoc
1   /*
2    *    Copyright 2009-2021 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.submitted.sptests;
17  
18  import static org.junit.jupiter.api.Assertions.assertEquals;
19  import static org.junit.jupiter.api.Assertions.assertNotNull;
20  import static org.junit.jupiter.api.Assertions.assertNull;
21  
22  import java.io.Reader;
23  import java.sql.Array;
24  import java.sql.SQLException;
25  import java.util.Date;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.ibatis.BaseDataTest;
31  import org.apache.ibatis.io.Resources;
32  import org.apache.ibatis.jdbc.ScriptRunner;
33  import org.apache.ibatis.session.SqlSession;
34  import org.apache.ibatis.session.SqlSessionFactory;
35  import org.apache.ibatis.session.SqlSessionFactoryBuilder;
36  import org.junit.jupiter.api.BeforeAll;
37  import org.junit.jupiter.api.Test;
38  
39  class SPTest {
40    private static SqlSessionFactory sqlSessionFactory;
41  
42    @BeforeAll
43    static void initDatabase() throws Exception {
44      try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/sptests/MapperConfig.xml")) {
45        sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
46      }
47  
48      ScriptRunner runner = new ScriptRunner(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource().getConnection());
49      runner.setDelimiter("go");
50      runner.setLogWriter(null);
51      runner.setErrorLogWriter(null);
52      BaseDataTest.runScript(runner, "org/apache/ibatis/submitted/sptests/CreateDB.sql");
53    }
54  
55    /*
56     * This test shows how to use input and output parameters in a stored
57     * procedure. This procedure does not return a result set.
58     *
59     * This test shows using a multi-property parameter.
60     */
61    @Test
62    void testAdderAsSelect() {
63      try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
64        Parameter parameter = new Parameter();
65        parameter.setAddend1(2);
66        parameter.setAddend2(3);
67  
68        SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
69        spMapper.adderAsSelect(parameter);
70  
71        assertEquals((Integer) 5, parameter.getSum());
72      }
73    }
74  
75    /*
76     * This test shows how to use input and output parameters in a stored
77     * procedure. This procedure does not return a result set.
78     *
79     * This test shows using a multi-property parameter.
80     */
81    @Test
82    void testAdderAsSelectDoubleCall1() {
83      try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
84        Parameter parameter = new Parameter();
85        parameter.setAddend1(2);
86        parameter.setAddend2(3);
87  
88        SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
89  
90        spMapper.adderAsSelect(parameter);
91        assertEquals((Integer) 5, parameter.getSum());
92  
93        parameter = new Parameter();
94        parameter.setAddend1(2);
95        parameter.setAddend2(3);
96        spMapper.adderAsSelect(parameter);
97        assertEquals((Integer) 5, parameter.getSum());
98      }
99    }
100 
101   /*
102    * This test shows how to use input and output parameters in a stored
103    * procedure. This procedure does not return a result set.
104    *
105    * This test also demonstrates session level cache for output parameters.
106    *
107    * This test shows using a multi-property parameter.
108    */
109   @Test
110   void testAdderAsSelectDoubleCall2() {
111     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
112       Parameter parameter = new Parameter();
113       parameter.setAddend1(2);
114       parameter.setAddend2(3);
115 
116       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
117 
118       spMapper.adderAsSelect(parameter);
119       assertEquals((Integer) 5, parameter.getSum());
120 
121       parameter = new Parameter();
122       parameter.setAddend1(4);
123       parameter.setAddend2(5);
124       spMapper.adderAsSelect(parameter);
125       assertEquals((Integer) 9, parameter.getSum());
126     }
127   }
128 
129   /*
130    * This test shows how to call a stored procedure defined as <update> rather
131    * then <select>. Of course, this only works if you are not returning a result
132    * set.
133    *
134    * This test shows using a multi-property parameter.
135    */
136   @Test
137   void testAdderAsUpdate() {
138     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
139       Parameter parameter = new Parameter();
140       parameter.setAddend1(2);
141       parameter.setAddend2(3);
142 
143       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
144 
145       spMapper.adderAsUpdate(parameter);
146       assertEquals((Integer) 5, parameter.getSum());
147 
148       parameter = new Parameter();
149       parameter.setAddend1(2);
150       parameter.setAddend2(3);
151       spMapper.adderAsUpdate(parameter);
152       assertEquals((Integer) 5, parameter.getSum());
153     }
154   }
155 
156   // issue #145
157   @Test
158   void testEchoDate() {
159     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
160       HashMap<String, Object> parameter = new HashMap<>();
161       Date now = new Date();
162       parameter.put("input date", now);
163 
164       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
165       spMapper.echoDate(parameter);
166 
167       java.sql.Date outDate = new java.sql.Date(now.getTime());
168       assertEquals(outDate.toString(), parameter.get("output date").toString());
169     }
170   }
171 
172   /*
173    * This test shows the use of a declared parameter map. We generally prefer
174    * inline parameters, because the syntax is more intuitive (no pesky question
175    * marks), but a parameter map will work.
176    */
177   @Test
178   void testAdderAsUpdateWithParameterMap() {
179     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
180       Map<String, Object> parms = new HashMap<>();
181       parms.put("addend1", 3);
182       parms.put("addend2", 4);
183 
184       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
185 
186       spMapper.adderWithParameterMap(parms);
187       assertEquals(7, parms.get("sum"));
188 
189       parms = new HashMap<>();
190       parms.put("addend1", 2);
191       parms.put("addend2", 3);
192       spMapper.adderWithParameterMap(parms);
193       assertEquals(5, parms.get("sum"));
194     }
195   }
196 
197   /*
198    * This test shows how to use an input parameter and return a result set from
199    * a stored procedure.
200    *
201    * This test shows using a single value parameter.
202    */
203   @Test
204   void testCallWithResultSet1() {
205     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
206       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
207 
208       Name name = spMapper.getName(1);
209       assertNotNull(name);
210       assertEquals("Wilma", name.getFirstName());
211     }
212   }
213 
214   /*
215    * This test shows how to use an input and output parameters and return a
216    * result set from a stored procedure.
217    *
218    * This test shows using a single value parameter.
219    */
220   @Test
221   void testCallWithResultSet2() {
222     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
223       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
224 
225       Map<String, Object> parms = new HashMap<>();
226       parms.put("lowestId", 1);
227       List<Name> names = spMapper.getNames(parms);
228       assertEquals(3, names.size());
229       assertEquals(3, parms.get("totalRows"));
230     }
231   }
232 
233   /*
234    * This test shows how to use an input and output parameters and return a
235    * result set from a stored procedure.
236    *
237    * This test shows using a Map parameter.
238    */
239   @Test
240   void testCallWithResultSet3() {
241     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
242       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
243 
244       Map<String, Object> parms = new HashMap<>();
245       parms.put("lowestId", 2);
246       List<Name> names = spMapper.getNames(parms);
247       assertEquals(2, parms.get("totalRows"));
248       assertEquals(2, names.size());
249 
250       parms = new HashMap<>();
251       parms.put("lowestId", 3);
252       names = spMapper.getNames(parms);
253       assertEquals(1, names.size());
254       assertEquals(1, parms.get("totalRows"));
255     }
256   }
257 
258   /*
259    * This test shows how to use an input and output parameters and return a
260    * result set from a stored procedure.
261    *
262    * This test shows using a Map parameter.
263    */
264   @Test
265   void testCallWithResultSet4() {
266     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
267       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
268 
269       Map<String, Object> parms = new HashMap<>();
270       parms.put("lowestId", 2);
271       List<Name> names = spMapper.getNames(parms);
272       assertEquals(2, parms.get("totalRows"));
273       assertEquals(2, names.size());
274 
275       parms = new HashMap<>();
276       parms.put("lowestId", 2);
277       names = spMapper.getNames(parms);
278       assertEquals(2, names.size());
279       assertEquals(2, parms.get("totalRows"));
280     }
281   }
282 
283   /*
284    * This test shows how to use the ARRAY JDBC type with MyBatis.
285    *
286    * @throws SQLException
287    */
288   @Test
289   void testGetNamesWithArray() throws SQLException {
290     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
291       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
292 
293       Array array = sqlSession.getConnection().createArrayOf("int", new Integer[] { 1, 2, 5 });
294 
295       Map<String, Object> parms = new HashMap<>();
296       parms.put("ids", array);
297       List<Name> names = spMapper.getNamesWithArray(parms);
298       Object[] returnedIds = (Object[]) parms.get("returnedIds");
299       assertEquals(4, returnedIds.length);
300       assertEquals(3, parms.get("requestedRows"));
301       assertEquals(2, names.size());
302     }
303   }
304 
305   /*
306    * This test shows how to call procedures that return multiple result sets
307    *
308    * @throws SQLException
309    */
310   @Test
311   void testGetNamesAndItems() {
312     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
313       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
314 
315       List<List<?>> results = spMapper.getNamesAndItems();
316       assertEquals(2, results.size());
317       assertEquals(4, results.get(0).size());
318       assertEquals(3, results.get(1).size());
319     }
320   }
321 
322   /*
323    * This test shows how to use input and output parameters in a stored
324    * procedure. This procedure does not return a result set.
325    *
326    * This test shows using a multi-property parameter.
327    *
328    * This test shows using annotations for stored procedures
329    */
330   @Test
331   void testAdderAsSelectAnnotated() {
332     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
333       Parameter parameter = new Parameter();
334       parameter.setAddend1(2);
335       parameter.setAddend2(3);
336 
337       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
338       spMapper.adderAsSelectAnnotated(parameter);
339 
340       assertEquals((Integer) 5, parameter.getSum());
341     }
342   }
343 
344   /*
345    * This test shows how to use input and output parameters in a stored
346    * procedure. This procedure does not return a result set.
347    *
348    * This test shows using a multi-property parameter.
349    *
350    * This test shows using annotations for stored procedures
351    */
352   @Test
353   void testAdderAsSelectDoubleCallAnnotated1() {
354     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
355       Parameter parameter = new Parameter();
356       parameter.setAddend1(2);
357       parameter.setAddend2(3);
358 
359       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
360 
361       spMapper.adderAsSelectAnnotated(parameter);
362       assertEquals((Integer) 5, parameter.getSum());
363 
364       parameter = new Parameter();
365       parameter.setAddend1(2);
366       parameter.setAddend2(3);
367       spMapper.adderAsSelectAnnotated(parameter);
368       assertEquals((Integer) 5, parameter.getSum());
369     }
370   }
371 
372   /*
373    * This test shows how to use input and output parameters in a stored
374    * procedure. This procedure does not return a result set.
375    *
376    * This test also demonstrates session level cache for output parameters.
377    *
378    * This test shows using a multi-property parameter.
379    *
380    * This test shows using annotations for stored procedures
381    */
382   @Test
383   void testAdderAsSelectDoubleCallAnnotated2() {
384     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
385       Parameter parameter = new Parameter();
386       parameter.setAddend1(2);
387       parameter.setAddend2(3);
388 
389       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
390 
391       spMapper.adderAsSelectAnnotated(parameter);
392       assertEquals((Integer) 5, parameter.getSum());
393 
394       parameter = new Parameter();
395       parameter.setAddend1(4);
396       parameter.setAddend2(5);
397       spMapper.adderAsSelectAnnotated(parameter);
398       assertEquals((Integer) 9, parameter.getSum());
399     }
400   }
401 
402   /*
403    * This test shows how to call a stored procedure defined as <update> rather
404    * then <select>. Of course, this only works if you are not returning a result
405    * set.
406    *
407    * This test shows using a multi-property parameter.
408    *
409    * This test shows using annotations for stored procedures
410    */
411   @Test
412   void testAdderAsUpdateAnnotated() {
413     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
414       Parameter parameter = new Parameter();
415       parameter.setAddend1(2);
416       parameter.setAddend2(3);
417 
418       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
419 
420       spMapper.adderAsUpdateAnnotated(parameter);
421       assertEquals((Integer) 5, parameter.getSum());
422 
423       parameter = new Parameter();
424       parameter.setAddend1(2);
425       parameter.setAddend2(3);
426       spMapper.adderAsUpdateAnnotated(parameter);
427       assertEquals((Integer) 5, parameter.getSum());
428     }
429   }
430 
431   /*
432    * This test shows how to use an input parameter and return a result set from
433    * a stored procedure.
434    *
435    * This test shows using a single value parameter.
436    *
437    * This test shows using annotations for stored procedures
438    */
439   @Test
440   void testCallWithResultSet1Annotated() {
441     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
442       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
443 
444       Name name = spMapper.getNameAnnotated(1);
445       assertNotNull(name);
446       assertEquals("Wilma", name.getFirstName());
447     }
448   }
449 
450   /*
451    * This test shows how to use an input parameter and return a result set from
452    * a stored procedure.
453    *
454    * This test shows using a single value parameter.
455    *
456    * This test shows using annotations for stored procedures and using a
457    * resultMap in XML
458    */
459   @Test
460   void testCallWithResultSet1_a2() {
461     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
462       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
463 
464       Name name = spMapper.getNameAnnotatedWithXMLResultMap(1);
465       assertNotNull(name);
466       assertEquals("Wilma", name.getFirstName());
467     }
468   }
469 
470   /*
471    * This test shows how to use an input and output parameters and return a
472    * result set from a stored procedure.
473    *
474    * This test shows using a single value parameter.
475    *
476    * This test shows using annotations for stored procedures
477    */
478   @Test
479   void testCallWithResultSet2_a1() {
480     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
481       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
482 
483       Map<String, Object> parms = new HashMap<>();
484       parms.put("lowestId", 1);
485       List<Name> names = spMapper.getNamesAnnotated(parms);
486       assertEquals(3, names.size());
487       assertEquals(3, parms.get("totalRows"));
488     }
489   }
490 
491   /*
492    * This test shows how to use an input and output parameters and return a
493    * result set from a stored procedure.
494    *
495    * This test shows using a single value parameter.
496    *
497    * This test shows using annotations for stored procedures and using a
498    * resultMap in XML
499    */
500   @Test
501   void testCallWithResultSet2_a2() {
502     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
503       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
504 
505       Map<String, Object> parms = new HashMap<>();
506       parms.put("lowestId", 1);
507       List<Name> names = spMapper.getNamesAnnotatedWithXMLResultMap(parms);
508       assertEquals(3, names.size());
509       assertEquals(3, parms.get("totalRows"));
510     }
511   }
512 
513   /*
514    * This test shows how to use an input and output parameters and return a
515    * result set from a stored procedure.
516    *
517    * This test shows using a Map parameter.
518    *
519    * This test shows using annotations for stored procedures
520    */
521   @Test
522   void testCallWithResultSet3_a1() {
523     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
524       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
525 
526       Map<String, Object> parms = new HashMap<>();
527       parms.put("lowestId", 2);
528       List<Name> names = spMapper.getNamesAnnotated(parms);
529       assertEquals(2, parms.get("totalRows"));
530       assertEquals(2, names.size());
531 
532       parms = new HashMap<>();
533       parms.put("lowestId", 3);
534       names = spMapper.getNamesAnnotated(parms);
535       assertEquals(1, names.size());
536       assertEquals(1, parms.get("totalRows"));
537     }
538   }
539 
540   /*
541    * This test shows how to use an input and output parameters and return a
542    * result set from a stored procedure.
543    *
544    * This test shows using a Map parameter.
545    *
546    * This test shows using annotations for stored procedures and using a
547    * resultMap in XML
548    */
549   @Test
550   void testCallWithResultSet3_a2() {
551     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
552       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
553 
554       Map<String, Object> parms = new HashMap<>();
555       parms.put("lowestId", 2);
556       List<Name> names = spMapper.getNamesAnnotatedWithXMLResultMap(parms);
557       assertEquals(2, parms.get("totalRows"));
558       assertEquals(2, names.size());
559 
560       parms = new HashMap<>();
561       parms.put("lowestId", 3);
562       names = spMapper.getNamesAnnotatedWithXMLResultMap(parms);
563       assertEquals(1, names.size());
564       assertEquals(1, parms.get("totalRows"));
565     }
566   }
567 
568   /*
569    * This test shows how to use an input and output parameters and return a
570    * result set from a stored procedure.
571    *
572    * This test shows using a Map parameter.
573    *
574    * This test shows using annotations for stored procedures
575    */
576   @Test
577   void testCallWithResultSet4_a1() {
578     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
579       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
580 
581       Map<String, Object> parms = new HashMap<>();
582       parms.put("lowestId", 2);
583       List<Name> names = spMapper.getNamesAnnotated(parms);
584       assertEquals(2, parms.get("totalRows"));
585       assertEquals(2, names.size());
586 
587       parms = new HashMap<>();
588       parms.put("lowestId", 2);
589       names = spMapper.getNamesAnnotated(parms);
590       assertEquals(2, names.size());
591       assertEquals(2, parms.get("totalRows"));
592     }
593   }
594 
595   /*
596    * This test shows how to use an input and output parameters and return a
597    * result set from a stored procedure.
598    *
599    * This test shows using a Map parameter.
600    *
601    * This test shows using annotations for stored procedures and using a
602    * resultMap in XML
603    */
604   @Test
605   void testCallWithResultSet4_a2() {
606     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
607       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
608 
609       Map<String, Object> parms = new HashMap<>();
610       parms.put("lowestId", 2);
611       List<Name> names = spMapper.getNamesAnnotatedWithXMLResultMap(parms);
612       assertEquals(2, parms.get("totalRows"));
613       assertEquals(2, names.size());
614 
615       parms = new HashMap<>();
616       parms.put("lowestId", 2);
617       names = spMapper.getNamesAnnotatedWithXMLResultMap(parms);
618       assertEquals(2, names.size());
619       assertEquals(2, parms.get("totalRows"));
620     }
621   }
622 
623   /*
624    *
625    * This test shows using a two named parameters.
626    *
627    * This test shows using annotations for stored procedures and using a
628    * resultMap in XML
629    */
630   @Test
631   void testCallLowHighWithResultSet() {
632     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
633       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
634       List<Name> names = spMapper.getNamesAnnotatedLowHighWithXMLResultMap(1, 1);
635       assertEquals(1, names.size());
636     }
637   }
638 
639   /*
640    * This test shows how to use the ARRAY JDBC type with MyBatis.
641    *
642    * This test shows using annotations for stored procedures
643    *
644    * @throws SQLException
645    */
646   @Test
647   void testGetNamesWithArray_a1() throws SQLException {
648     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
649       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
650 
651       Array array = sqlSession.getConnection().createArrayOf("int", new Integer[] { 1, 2, 5 });
652 
653       Map<String, Object> parms = new HashMap<>();
654       parms.put("ids", array);
655       List<Name> names = spMapper.getNamesWithArrayAnnotated(parms);
656       Object[] returnedIds = (Object[]) parms.get("returnedIds");
657       assertEquals(4, returnedIds.length);
658       assertEquals(3, parms.get("requestedRows"));
659       assertEquals(2, names.size());
660     }
661   }
662 
663   /*
664    * This test shows how to use the ARRAY JDBC type with MyBatis.
665    *
666    * This test shows using annotations for stored procedures and using a
667    * resultMap in XML
668    *
669    * @throws SQLException
670    */
671   @Test
672   void testGetNamesWithArray_a2() throws SQLException {
673     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
674       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
675 
676       Array array = sqlSession.getConnection().createArrayOf("int", new Integer[] { 1, 2, 5 });
677 
678       Map<String, Object> parms = new HashMap<>();
679       parms.put("ids", array);
680       List<Name> names = spMapper.getNamesWithArrayAnnotatedWithXMLResultMap(parms);
681       Object[] returnedIds = (Object[]) parms.get("returnedIds");
682       assertEquals(4, returnedIds.length);
683       assertEquals(3, parms.get("requestedRows"));
684       assertEquals(2, names.size());
685     }
686   }
687 
688   /*
689    * This test shows how to call procedures that return multiple result sets
690    *
691    * This test shows using annotations for stored procedures and referring to
692    * multiple resultMaps in XML
693    *
694    * @throws SQLException
695    */
696   @Test
697   void testGetNamesAndItems_a2() {
698     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
699       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
700 
701       List<List<?>> results = spMapper.getNamesAndItemsAnnotatedWithXMLResultMap();
702       assertEquals(2, results.size());
703       assertEquals(4, results.get(0).size());
704       assertEquals(3, results.get(1).size());
705     }
706   }
707 
708   @Test
709   void testGetNamesAndItems_a3() {
710     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
711       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
712 
713       List<List<?>> results = spMapper.getNamesAndItemsAnnotatedWithXMLResultMapArray();
714       assertEquals(2, results.size());
715       assertEquals(4, results.get(0).size());
716       assertEquals(3, results.get(1).size());
717     }
718   }
719 
720   @Test
721   void testGetNamesAndItemsLinked() {
722     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
723       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
724 
725       List<Name> names = spMapper.getNamesAndItemsLinked();
726       assertEquals(4, names.size());
727       assertEquals(2, names.get(0).getItems().size());
728       assertEquals(1, names.get(1).getItems().size());
729       assertNull(names.get(2).getItems());
730       assertNull(names.get(3).getItems());
731     }
732   }
733 
734   @Test
735   void testGetNamesAndItemsLinkedWithNoMatchingInfo() {
736     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
737       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
738 
739       List<Name> names = spMapper.getNamesAndItemsLinkedById(0);
740       assertEquals(1, names.size());
741       assertEquals(2, names.get(0).getItems().size());
742     }
743   }
744 
745   @Test
746   void testMultipleForeignKeys() {
747     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
748       SPMapper spMapper = sqlSession.getMapper(SPMapper.class);
749       List<Book> books = spMapper.getBookAndGenre();
750       assertEquals("Book1", books.get(0).getName());
751       assertEquals("Genre1", books.get(0).getGenre().getName());
752       assertEquals("Book2", books.get(1).getName());
753       assertEquals("Genre2", books.get(1).getGenre().getName());
754       assertEquals("Book3", books.get(2).getName());
755       assertEquals("Genre1", books.get(2).getGenre().getName());
756     }
757   }
758 }