View Javadoc
1   /**
2    *    Copyright 2009-2019 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.keygen;
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.Reader;
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.HashMap;
26  import java.util.HashSet;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Set;
30  
31  import org.apache.ibatis.BaseDataTest;
32  import org.apache.ibatis.exceptions.PersistenceException;
33  import org.apache.ibatis.io.Resources;
34  import org.apache.ibatis.session.ExecutorType;
35  import org.apache.ibatis.session.SqlSession;
36  import org.apache.ibatis.session.SqlSessionFactory;
37  import org.apache.ibatis.session.SqlSessionFactoryBuilder;
38  import org.junit.jupiter.api.BeforeAll;
39  import org.junit.jupiter.api.Test;
40  
41  /**
42   * @author liuzh
43   */
44  class Jdbc3KeyGeneratorTest {
45  
46    private static SqlSessionFactory sqlSessionFactory;
47  
48    @BeforeAll
49    static void setUp() throws Exception {
50      // create an SqlSessionFactory
51      try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/keygen/MapperConfig.xml")) {
52        sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
53      }
54  
55      // populate in-memory database
56      BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),
57              "org/apache/ibatis/submitted/keygen/CreateDB.sql");
58    }
59  
60    @Test
61    void shouldAssignKeyToBean() {
62      try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
63        try {
64          CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
65          Country/keygen/Country.html#Country">Country country = new Country("China", "CN");
66          mapper.insertBean(country);
67          assertNotNull(country.getId());
68        } finally {
69          sqlSession.rollback();
70        }
71      }
72    }
73  
74    @Test
75    void shouldAssignKeyToBean_batch() {
76      try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
77        try {
78          CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
79          Countrykeygen/Country.html#Country">Country country1 = new Country("China", "CN");
80          mapper.insertBean(country1);
81          Countrykeygen/Country.html#Country">Country country2 = new Country("Canada", "CA");
82          mapper.insertBean(country2);
83          sqlSession.flushStatements();
84          sqlSession.clearCache();
85          assertNotNull(country1.getId());
86          assertNotNull(country2.getId());
87        } finally {
88          sqlSession.rollback();
89        }
90      }
91    }
92  
93    @Test
94    void shouldAssignKeyToNamedBean() {
95      try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
96        try {
97          CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
98          Country/keygen/Country.html#Country">Country country = new Country("China", "CN");
99          mapper.insertNamedBean(country);
100         assertNotNull(country.getId());
101       } finally {
102         sqlSession.rollback();
103       }
104     }
105   }
106 
107   @Test
108   void shouldAssignKeyToNamedBean_batch() {
109     try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
110       try {
111         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
112         Countrykeygen/Country.html#Country">Country country1 = new Country("China", "CN");
113         mapper.insertNamedBean(country1);
114         Countrykeygen/Country.html#Country">Country country2 = new Country("Canada", "CA");
115         mapper.insertNamedBean(country2);
116         sqlSession.flushStatements();
117         sqlSession.clearCache();
118         assertNotNull(country1.getId());
119         assertNotNull(country2.getId());
120       } finally {
121         sqlSession.rollback();
122       }
123     }
124   }
125 
126   @Test
127   void shouldAssignKeyToNamedBean_keyPropertyWithParamName() {
128     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
129       try {
130         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
131         Country/keygen/Country.html#Country">Country country = new Country("China", "CN");
132         mapper.insertNamedBean_keyPropertyWithParamName(country);
133         assertNotNull(country.getId());
134       } finally {
135         sqlSession.rollback();
136       }
137     }
138   }
139 
140   @Test
141   void shouldAssignKeyToNamedBean_keyPropertyWithParamName_batch() {
142     try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
143       try {
144         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
145         Countrykeygen/Country.html#Country">Country country1 = new Country("China", "CN");
146         mapper.insertNamedBean_keyPropertyWithParamName(country1);
147         Countrykeygen/Country.html#Country">Country country2 = new Country("Canada", "CA");
148         mapper.insertNamedBean_keyPropertyWithParamName(country2);
149         sqlSession.flushStatements();
150         sqlSession.clearCache();
151         assertNotNull(country1.getId());
152         assertNotNull(country2.getId());
153       } finally {
154         sqlSession.rollback();
155       }
156     }
157   }
158 
159   @Test
160   void shouldAssignKeysToList() {
161     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
162       try {
163         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
164         List<Country> countries = new ArrayList<>();
165         countries.add(new Country("China", "CN"));
166         countries.add(new Country("United Kiongdom", "GB"));
167         countries.add(new Country("United States of America", "US"));
168         mapper.insertList(countries);
169         for (Country country : countries) {
170           assertNotNull(country.getId());
171         }
172       } finally {
173         sqlSession.rollback();
174       }
175     }
176   }
177 
178   @Test
179   void shouldAssignKeysToNamedList() {
180     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
181       try {
182         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
183         List<Country> countries = new ArrayList<>();
184         countries.add(new Country("China", "CN"));
185         countries.add(new Country("United Kiongdom", "GB"));
186         countries.add(new Country("United States of America", "US"));
187         mapper.insertNamedList(countries);
188         for (Country country : countries) {
189           assertNotNull(country.getId());
190         }
191       } finally {
192         sqlSession.rollback();
193       }
194     }
195   }
196 
197   @Test
198   void shouldAssingKeysToCollection() {
199     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
200       try {
201         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
202         Set<Country> countries = new HashSet<>();
203         countries.add(new Country("China", "CN"));
204         countries.add(new Country("United Kiongdom", "GB"));
205         mapper.insertSet(countries);
206         for (Country country : countries) {
207           assertNotNull(country.getId());
208         }
209       } finally {
210         sqlSession.rollback();
211       }
212     }
213   }
214 
215   @Test
216   void shouldAssingKeysToNamedCollection() {
217     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
218       try {
219         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
220         Set<Country> countries = new HashSet<>();
221         countries.add(new Country("China", "CN"));
222         countries.add(new Country("United Kiongdom", "GB"));
223         mapper.insertNamedSet(countries);
224         for (Country country : countries) {
225           assertNotNull(country.getId());
226         }
227       } finally {
228         sqlSession.rollback();
229       }
230     }
231   }
232 
233   @Test
234   void shouldAssingKeysToArray() {
235     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
236       try {
237         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
238         Countrygen/Country.html#Country">Country[] countries = new Country[2];
239         countries[0] = new Country("China", "CN");
240         countries[1] = new Country("United Kiongdom", "GB");
241         mapper.insertArray(countries);
242         for (Country country : countries) {
243           assertNotNull(country.getId());
244         }
245       } finally {
246         sqlSession.rollback();
247       }
248     }
249   }
250 
251   @Test
252   void shouldAssingKeysToNamedArray() {
253     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
254       try {
255         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
256         Countrygen/Country.html#Country">Country[] countries = new Country[2];
257         countries[0] = new Country("China", "CN");
258         countries[1] = new Country("United Kiongdom", "GB");
259         mapper.insertNamedArray(countries);
260         for (Country country : countries) {
261           assertNotNull(country.getId());
262         }
263       } finally {
264         sqlSession.rollback();
265       }
266     }
267   }
268 
269   @Test
270   void shouldAssignKeyToBean_MultiParams() {
271     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
272       try {
273         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
274         Country/keygen/Country.html#Country">Country country = new Country("China", "CN");
275         mapper.insertMultiParams(country, 1);
276         assertNotNull(country.getId());
277       } finally {
278         sqlSession.rollback();
279       }
280     }
281   }
282 
283   @Test
284   void shouldFailIfKeyPropertyIsInvalid_NoParamName() {
285     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
286       try {
287         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
288         Country/keygen/Country.html#Country">Country country = new Country("China", "CN");
289         when(() -> mapper.insertMultiParams_keyPropertyWithoutParamName(country, 1));
290         then(caughtException()).isInstanceOf(PersistenceException.class).hasMessageContaining(
291             "Could not determine which parameter to assign generated keys to. "
292                 + "Note that when there are multiple parameters, 'keyProperty' must include the parameter name (e.g. 'param.id'). "
293                 + "Specified key properties are [id] and available parameters are [");
294       } finally {
295         sqlSession.rollback();
296       }
297     }
298   }
299 
300   @Test
301   void shouldFailIfKeyPropertyIsInvalid_WrongParamName() {
302     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
303       try {
304         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
305         Country/keygen/Country.html#Country">Country country = new Country("China", "CN");
306         when(() -> mapper.insertMultiParams_keyPropertyWithWrongParamName(country, 1));
307         then(caughtException()).isInstanceOf(PersistenceException.class).hasMessageContaining(
308             "Could not find parameter 'bogus'. "
309                 + "Note that when there are multiple parameters, 'keyProperty' must include the parameter name (e.g. 'param.id'). "
310                 + "Specified key properties are [bogus.id] and available parameters are [");
311       } finally {
312         sqlSession.rollback();
313       }
314     }
315   }
316 
317   @Test
318   void shouldAssignKeysToNamedList_MultiParams() {
319     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
320       try {
321         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
322         List<Country> countries = new ArrayList<>();
323         countries.add(new Country("China", "CN"));
324         countries.add(new Country("United Kiongdom", "GB"));
325         mapper.insertList_MultiParams(countries, 1);
326         for (Country country : countries) {
327           assertNotNull(country.getId());
328         }
329       } finally {
330         sqlSession.rollback();
331       }
332     }
333   }
334 
335   @Test
336   void shouldAssignKeysToNamedCollection_MultiParams() {
337     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
338       try {
339         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
340         Set<Country> countries = new HashSet<>();
341         countries.add(new Country("China", "CN"));
342         countries.add(new Country("United Kiongdom", "GB"));
343         mapper.insertSet_MultiParams(countries, 1);
344         for (Country country : countries) {
345           assertNotNull(country.getId());
346         }
347       } finally {
348         sqlSession.rollback();
349       }
350     }
351   }
352 
353   @Test
354   void shouldAssignKeysToNamedArray_MultiParams() {
355     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
356       try {
357         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
358         Countrygen/Country.html#Country">Country[] countries = new Country[2];
359         countries[0] = new Country("China", "CN");
360         countries[1] = new Country("United Kiongdom", "GB");
361         mapper.insertArray_MultiParams(countries, 1);
362         for (Country country : countries) {
363           assertNotNull(country.getId());
364         }
365       } finally {
366         sqlSession.rollback();
367       }
368     }
369   }
370 
371   @Test
372   void shouldAssignMultipleGeneratedKeysToABean() {
373     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
374       try {
375         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
376         Planeted/keygen/Planet.html#Planet">Planet planet = new Planet();
377         planet.setName("pluto");
378         mapper.insertPlanet(planet);
379         assertEquals("pluto-" + planet.getId(), planet.getCode());
380       } finally {
381         sqlSession.rollback();
382       }
383     }
384   }
385 
386   @Test
387   void shouldAssignMultipleGeneratedKeysToBeans() {
388     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
389       try {
390         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
391         Planetd/keygen/Planet.html#Planet">Planet planet1 = new Planet();
392         planet1.setName("pluto");
393         Planetd/keygen/Planet.html#Planet">Planet planet2 = new Planet();
394         planet2.setName("neptune");
395         List<Planet> planets = Arrays.asList(planet1, planet2);
396         mapper.insertPlanets(planets);
397         assertEquals("pluto-" + planet1.getId(), planet1.getCode());
398         assertEquals("neptune-" + planet2.getId(), planet2.getCode());
399       } finally {
400         sqlSession.rollback();
401       }
402     }
403   }
404 
405   @Test
406   void shouldAssignMultipleGeneratedKeysToABean_MultiParams() {
407     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
408       try {
409         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
410         Planeted/keygen/Planet.html#Planet">Planet planet = new Planet();
411         planet.setName("pluto");
412         mapper.insertPlanet_MultiParams(planet, 1);
413         assertEquals("pluto-" + planet.getId(), planet.getCode());
414       } finally {
415         sqlSession.rollback();
416       }
417     }
418   }
419   @Test
420   void shouldAssignMultipleGeneratedKeysToABean_MultiParams_batch() {
421     try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
422       try {
423         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
424         Planetd/keygen/Planet.html#Planet">Planet planet1 = new Planet();
425         planet1.setName("pluto");
426         mapper.insertPlanet_MultiParams(planet1, 1);
427         Planetd/keygen/Planet.html#Planet">Planet planet2 = new Planet();
428         planet2.setName("neptune");
429         mapper.insertPlanet_MultiParams(planet2, 1);
430         sqlSession.flushStatements();
431         sqlSession.clearCache();
432         assertEquals("pluto-" + planet1.getId(), planet1.getCode());
433         assertEquals("neptune-" + planet2.getId(), planet2.getCode());
434       } finally {
435         sqlSession.rollback();
436       }
437     }
438   }
439 
440   @Test
441   void shouldAssignMultipleGeneratedKeysToBeans_MultiParams() {
442     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
443       try {
444         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
445         Planetd/keygen/Planet.html#Planet">Planet planet1 = new Planet();
446         planet1.setName("pluto");
447         Planetd/keygen/Planet.html#Planet">Planet planet2 = new Planet();
448         planet2.setName("neptune");
449         List<Planet> planets = Arrays.asList(planet1, planet2);
450         mapper.insertPlanets_MultiParams(planets, 1);
451         assertEquals("pluto-" + planet1.getId(), planet1.getCode());
452         assertEquals("neptune-" + planet2.getId(), planet2.getCode());
453       } finally {
454         sqlSession.rollback();
455       }
456     }
457   }
458 
459   @Test
460   void assigningMultipleKeysToDifferentParams() {
461     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
462       try {
463         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
464         Planeted/keygen/Planet.html#Planet">Planet planet = new Planet();
465         planet.setName("pluto");
466         Map<String, Object> map = new HashMap<>();
467         mapper.insertAssignKeysToTwoParams(planet, map);
468         assertNotNull(planet.getId());
469         assertNotNull(map.get("code"));
470       } finally {
471         sqlSession.rollback();
472       }
473     }
474   }
475 
476   @Test
477   void assigningMultipleKeysToDifferentParams_batch() {
478     try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
479       try {
480         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
481         Planetd/keygen/Planet.html#Planet">Planet planet1 = new Planet();
482         planet1.setName("pluto");
483         Map<String, Object> map1 = new HashMap<>();
484         mapper.insertAssignKeysToTwoParams(planet1, map1);
485         Planetd/keygen/Planet.html#Planet">Planet planet2 = new Planet();
486         planet2.setName("pluto");
487         Map<String, Object> map2 = new HashMap<>();
488         mapper.insertAssignKeysToTwoParams(planet2, map2);
489         sqlSession.flushStatements();
490         sqlSession.clearCache();
491         assertNotNull(planet1.getId());
492         assertNotNull(map1.get("code"));
493         assertNotNull(planet2.getId());
494         assertNotNull(map2.get("code"));
495       } finally {
496         sqlSession.rollback();
497       }
498     }
499   }
500 
501   @Test
502   void shouldErrorUndefineProperty() {
503     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
504       try {
505         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
506 
507         when(() -> mapper.insertUndefineKeyProperty(new Country("China", "CN")));
508         then(caughtException()).isInstanceOf(PersistenceException.class).hasMessageContaining(
509                 "### Error updating database.  Cause: org.apache.ibatis.executor.ExecutorException: Error getting generated key or setting result to parameter object. Cause: org.apache.ibatis.executor.ExecutorException: No setter found for the keyProperty 'country_id' in 'org.apache.ibatis.submitted.keygen.Country'.");
510       } finally {
511         sqlSession.rollback();
512       }
513     }
514   }
515 
516   @Test
517   void shouldFailIfTooManyGeneratedKeys() {
518     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
519       try {
520         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
521         when(() -> mapper.tooManyGeneratedKeys(new Country()));
522         then(caughtException()).isInstanceOf(PersistenceException.class).hasMessageContaining(
523             "Too many keys are generated. There are only 1 target objects.");
524       } finally {
525         sqlSession.rollback();
526       }
527     }
528   }
529 
530   @Test
531   void shouldFailIfTooManyGeneratedKeys_ParamMap() {
532     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
533       try {
534         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
535         when(() -> mapper.tooManyGeneratedKeysParamMap(new Country(), 1));
536         then(caughtException()).isInstanceOf(PersistenceException.class).hasMessageContaining(
537             "Too many keys are generated. There are only 1 target objects.");
538       } finally {
539         sqlSession.rollback();
540       }
541     }
542   }
543 
544   @Test
545   void shouldFailIfTooManyGeneratedKeys_Batch() {
546     try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
547       try {
548         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
549         mapper.tooManyGeneratedKeysParamMap(new Country(), 1);
550         mapper.tooManyGeneratedKeysParamMap(new Country(), 1);
551         when(sqlSession::flushStatements);
552         then(caughtException()).isInstanceOf(PersistenceException.class).hasMessageContaining(
553             "Too many keys are generated. There are only 2 target objects.");
554       } finally {
555         sqlSession.rollback();
556       }
557     }
558   }
559 
560   @Test
561   void shouldAssignKeysToListWithoutInvokingEqualsNorHashCode() {
562     // gh-1719
563     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
564       try {
565         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
566         List<NpeCountry> countries = new ArrayList<>();
567         countries.add(new NpeCountry("China", "CN"));
568         countries.add(new NpeCountry("United Kiongdom", "GB"));
569         countries.add(new NpeCountry("United States of America", "US"));
570         mapper.insertWeirdCountries(countries);
571         for (NpeCountry country : countries) {
572           assertNotNull(country.getId());
573         }
574       } finally {
575         sqlSession.rollback();
576       }
577     }
578   }
579 
580   @Test
581   void shouldAssignKeyToAParamWithTrickyName() {
582     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
583       try {
584         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
585         Country/keygen/Country.html#Country">Country country = new Country("China", "CN");
586         mapper.singleParamWithATrickyName(country);
587         assertNotNull(country.getId());
588       } finally {
589         sqlSession.rollback();
590       }
591     }
592   }
593 
594   @Test
595   void shouldAssingKeysToAMap() {
596     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
597       try {
598         CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
599         Map<String, Object> map = new HashMap<>();
600         map.put("countrycode", "CN");
601         map.put("countryname", "China");
602         mapper.insertMap(map);
603         assertNotNull(map.get("id"));
604       } finally {
605         sqlSession.rollback();
606       }
607     }
608   }
609 }