1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.submitted.sqlprovider;
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 import static org.junit.jupiter.api.Assertions.assertTrue;
22 import static org.junit.jupiter.api.Assertions.fail;
23
24 import java.io.Reader;
25 import java.lang.reflect.Method;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31
32 import org.apache.ibatis.BaseDataTest;
33 import org.apache.ibatis.annotations.DeleteProvider;
34 import org.apache.ibatis.annotations.InsertProvider;
35 import org.apache.ibatis.annotations.Param;
36 import org.apache.ibatis.annotations.SelectProvider;
37 import org.apache.ibatis.annotations.UpdateProvider;
38 import org.apache.ibatis.binding.MapperMethod;
39 import org.apache.ibatis.builder.BuilderException;
40 import org.apache.ibatis.builder.annotation.ProviderContext;
41 import org.apache.ibatis.builder.annotation.ProviderSqlSource;
42 import org.apache.ibatis.io.Resources;
43 import org.apache.ibatis.session.Configuration;
44 import org.apache.ibatis.session.SqlSession;
45 import org.apache.ibatis.session.SqlSessionFactory;
46 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
47 import org.junit.jupiter.api.BeforeAll;
48 import org.junit.jupiter.api.Test;
49
50 class SqlProviderTest {
51
52 private static SqlSessionFactory sqlSessionFactory;
53 private static SqlSessionFactory sqlSessionFactoryForDerby;
54
55 @BeforeAll
56 static void setUp() throws Exception {
57
58 try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/sqlprovider/mybatis-config.xml")) {
59 sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
60 sqlSessionFactory.getConfiguration().addMapper(StaticMethodSqlProviderMapper.class);
61 sqlSessionFactory.getConfiguration().addMapper(DatabaseIdMapper.class);
62 }
63
64 BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),
65 "org/apache/ibatis/submitted/sqlprovider/CreateDB.sql");
66
67
68 try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/sqlprovider/mybatis-config.xml")) {
69 sqlSessionFactoryForDerby = new SqlSessionFactoryBuilder().build(reader, "development-derby");
70 sqlSessionFactoryForDerby.getConfiguration().addMapper(DatabaseIdMapper.class);
71 }
72 }
73
74
75 @Test
76 void shouldGetTwoUsers() {
77 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
78 Mapper mapper = sqlSession.getMapper(Mapper.class);
79 List<Integer> list = new ArrayList<>();
80 list.add(1);
81 list.add(3);
82 List<User> users = mapper.getUsers(list);
83 assertEquals(2, users.size());
84 assertEquals("User1", users.get(0).getName());
85 assertEquals("User3", users.get(1).getName());
86 }
87 }
88
89
90 @Test
91 void shouldGetOneUser() {
92 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
93 Mapper mapper = sqlSession.getMapper(Mapper.class);
94 {
95 User user = mapper.getUser(4);
96 assertNotNull(user);
97 assertEquals("User4", user.getName());
98 }
99 {
100 User user = mapper.getUser(null);
101 assertNull(user);
102 }
103 }
104 }
105
106
107 @Test
108 void shouldGetAllUsers() {
109 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
110 Mapper mapper = sqlSession.getMapper(Mapper.class);
111 List<User> users = mapper.getAllUsers();
112 assertEquals(4, users.size());
113 assertEquals("User1", users.get(0).getName());
114 assertEquals("User2", users.get(1).getName());
115 assertEquals("User3", users.get(2).getName());
116 assertEquals("User4", users.get(3).getName());
117 }
118 }
119
120
121 @Test
122 void shouldGetUsersByCriteria() {
123 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
124 Mapper mapper = sqlSession.getMapper(Mapper.class);
125 {
126 User criteria = new User();
127 criteria.setId(1);
128 List<User> users = mapper.getUsersByCriteria(criteria);
129 assertEquals(1, users.size());
130 assertEquals("User1", users.get(0).getName());
131 }
132 {
133 User criteria = new User();
134 criteria.setName("User");
135 List<User> users = mapper.getUsersByCriteria(criteria);
136 assertEquals(4, users.size());
137 assertEquals("User1", users.get(0).getName());
138 assertEquals("User2", users.get(1).getName());
139 assertEquals("User3", users.get(2).getName());
140 assertEquals("User4", users.get(3).getName());
141 }
142 }
143 }
144
145
146 @Test
147 void shouldGetUsersByCriteriaMap() {
148 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
149 Mapper mapper = sqlSession.getMapper(Mapper.class);
150 {
151 Map<String, Object> criteria = new HashMap<>();
152 criteria.put("id", 1);
153 List<User> users = mapper.getUsersByCriteriaMap(criteria);
154 assertEquals(1, users.size());
155 assertEquals("User1", users.get(0).getName());
156 }
157 {
158 Map<String, Object> criteria = new HashMap<>();
159 criteria.put("name", "User");
160 List<User> users = mapper.getUsersByCriteriaMap(criteria);
161 assertEquals(4, users.size());
162 assertEquals("User1", users.get(0).getName());
163 assertEquals("User2", users.get(1).getName());
164 assertEquals("User3", users.get(2).getName());
165 assertEquals("User4", users.get(3).getName());
166 }
167 }
168 }
169
170 @Test
171 void shouldGetUsersByCriteriaMapWithParam() {
172 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
173 Mapper mapper = sqlSession.getMapper(Mapper.class);
174 {
175 Map<String, Object> criteria = new HashMap<>();
176 criteria.put("id", 1);
177 List<User> users = mapper.getUsersByCriteriaMapWithParam(criteria);
178 assertEquals(1, users.size());
179 assertEquals("User1", users.get(0).getName());
180 }
181 {
182 Map<String, Object> criteria = new HashMap<>();
183 criteria.put("name", "User");
184 List<User> users = mapper.getUsersByCriteriaMapWithParam(criteria);
185 assertEquals(4, users.size());
186 assertEquals("User1", users.get(0).getName());
187 assertEquals("User2", users.get(1).getName());
188 assertEquals("User3", users.get(2).getName());
189 assertEquals("User4", users.get(3).getName());
190 }
191 }
192 }
193
194
195 @Test
196 void shouldGetUsersByName() {
197 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
198 Mapper mapper = sqlSession.getMapper(Mapper.class);
199 List<User> users = mapper.getUsersByName("User", "id DESC");
200 assertEquals(4, users.size());
201 assertEquals("User4", users.get(0).getName());
202 assertEquals("User3", users.get(1).getName());
203 assertEquals("User2", users.get(2).getName());
204 assertEquals("User1", users.get(3).getName());
205 }
206 }
207
208
209 @Test
210 void shouldGetUsersByNameUsingMap() {
211 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
212 Mapper mapper = sqlSession.getMapper(Mapper.class);
213 List<User> users = mapper.getUsersByNameUsingMap("User", "id DESC");
214 assertEquals(4, users.size());
215 assertEquals("User4", users.get(0).getName());
216 assertEquals("User3", users.get(1).getName());
217 assertEquals("User2", users.get(2).getName());
218 assertEquals("User1", users.get(3).getName());
219 }
220 }
221
222
223 @Test
224 void shouldGetUsersByNameWithParamNameAndOrderBy() {
225 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
226 Mapper mapper = sqlSession.getMapper(Mapper.class);
227 List<User> users = mapper.getUsersByNameWithParamNameAndOrderBy("User", "id DESC");
228 assertEquals(4, users.size());
229 assertEquals("User4", users.get(0).getName());
230 assertEquals("User3", users.get(1).getName());
231 assertEquals("User2", users.get(2).getName());
232 assertEquals("User1", users.get(3).getName());
233 }
234 }
235
236
237 @Test
238 void shouldGetUsersByNameWithParamNameUsingMap() {
239 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
240 Mapper mapper = sqlSession.getMapper(Mapper.class);
241 List<User> users = mapper.getUsersByNameWithParamNameAndOrderBy("User", "id DESC");
242 assertEquals(4, users.size());
243 assertEquals("User4", users.get(0).getName());
244 assertEquals("User3", users.get(1).getName());
245 assertEquals("User2", users.get(2).getName());
246 assertEquals("User1", users.get(3).getName());
247 }
248 }
249
250
251 @Test
252 void shouldGetUsersByNameWithParamName() {
253 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
254 Mapper mapper = sqlSession.getMapper(Mapper.class);
255 {
256 List<User> users = mapper.getUsersByNameWithParamName("User");
257 assertEquals(4, users.size());
258 assertEquals("User4", users.get(0).getName());
259 assertEquals("User3", users.get(1).getName());
260 assertEquals("User2", users.get(2).getName());
261 assertEquals("User1", users.get(3).getName());
262 }
263 {
264 List<User> users = mapper.getUsersByNameWithParamName(null);
265 assertEquals(4, users.size());
266 assertEquals("User4", users.get(0).getName());
267 assertEquals("User3", users.get(1).getName());
268 assertEquals("User2", users.get(2).getName());
269 assertEquals("User1", users.get(3).getName());
270 }
271 }
272 }
273
274 @Test
275 void methodNotFound() throws NoSuchMethodException {
276 try {
277 Class<?> mapperType = ErrorMapper.class;
278 Method mapperMethod = mapperType.getMethod("methodNotFound");
279 new ProviderSqlSource(new Configuration(), mapperMethod.getAnnotation(SelectProvider.class), mapperType,
280 mapperMethod);
281 fail();
282 } catch (BuilderException e) {
283 assertTrue(e.getMessage().contains(
284 "Error creating SqlSource for SqlProvider. Method 'methodNotFound' not found in SqlProvider 'org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorSqlBuilder'."));
285 }
286 }
287
288 @Test
289 void methodOverload() throws NoSuchMethodException {
290 try {
291 Class<?> mapperType = ErrorMapper.class;
292 Method mapperMethod = mapperType.getMethod("methodOverload", String.class);
293 new ProviderSqlSource(new Configuration(), mapperMethod.getAnnotation(SelectProvider.class), mapperType,
294 mapperMethod);
295 fail();
296 } catch (BuilderException e) {
297 assertTrue(e.getMessage().contains(
298 "Error creating SqlSource for SqlProvider. Method 'overload' is found multiple in SqlProvider 'org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorSqlBuilder'. Sql provider method can not overload."));
299 }
300 }
301
302 @Test
303 @SuppressWarnings("deprecation")
304 void notSqlProvider() throws NoSuchMethodException {
305 Object testAnnotation = getClass().getDeclaredMethod("notSqlProvider").getAnnotation(Test.class);
306 try {
307 new ProviderSqlSource(new Configuration(), testAnnotation);
308 fail();
309 } catch (BuilderException e) {
310 assertTrue(e.getMessage().contains(
311 "Error creating SqlSource for SqlProvider. Cause: java.lang.NoSuchMethodException: org.junit.jupiter.api.Test.type()"));
312 }
313 }
314
315 @Test
316 void omitType() throws NoSuchMethodException {
317 try {
318 Class<?> mapperType = ErrorMapper.class;
319 Method mapperMethod = mapperType.getMethod("omitType");
320 new ProviderSqlSource(new Configuration(), mapperMethod.getAnnotation(SelectProvider.class), mapperType,
321 mapperMethod);
322 fail();
323 } catch (BuilderException e) {
324 assertTrue(e.getMessage().contains(
325 "Please specify either 'value' or 'type' attribute of @SelectProvider at the 'public abstract void org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorMapper.omitType()'."));
326 }
327 }
328
329 @Test
330 void differentTypeAndValue() throws NoSuchMethodException {
331 try {
332 Class<?> mapperType = ErrorMapper.class;
333 Method mapperMethod = mapperType.getMethod("differentTypeAndValue");
334 new ProviderSqlSource(new Configuration(), mapperMethod.getAnnotation(DeleteProvider.class), mapperType,
335 mapperMethod);
336 fail();
337 } catch (BuilderException e) {
338 assertTrue(e.getMessage().contains(
339 "Cannot specify different class on 'value' and 'type' attribute of @DeleteProvider at the 'public abstract void org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorMapper.differentTypeAndValue()'."));
340 }
341 }
342
343 @Test
344 void multipleProviderContext() throws NoSuchMethodException {
345 try {
346 Class<?> mapperType = ErrorMapper.class;
347 Method mapperMethod = mapperType.getMethod("multipleProviderContext");
348 new ProviderSqlSource(new Configuration(), mapperMethod.getAnnotation(SelectProvider.class), mapperType,
349 mapperMethod);
350 fail();
351 } catch (BuilderException e) {
352 assertTrue(e.getMessage().contains(
353 "Error creating SqlSource for SqlProvider. ProviderContext found multiple in SqlProvider method (org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorSqlBuilder.multipleProviderContext). ProviderContext can not define multiple in SqlProvider method argument."));
354 }
355 }
356
357 @Test
358 void notSupportParameterObjectOnMultipleArguments() throws NoSuchMethodException {
359 try {
360 Class<?> mapperType = Mapper.class;
361 Method mapperMethod = mapperType.getMethod("getUsersByName", String.class, String.class);
362 new ProviderSqlSource(new Configuration(), mapperMethod.getAnnotation(SelectProvider.class), mapperType,
363 mapperMethod).getBoundSql(new Object());
364 fail();
365 } catch (BuilderException e) {
366 assertTrue(e.getMessage().contains(
367 "Error invoking SqlProvider method 'public java.lang.String org.apache.ibatis.submitted.sqlprovider.OurSqlBuilder.buildGetUsersByNameQuery(java.lang.String,java.lang.String)' with specify parameter 'class java.lang.Object'. Cause: java.lang.IllegalArgumentException: wrong number of arguments"));
368 }
369 }
370
371 @Test
372 void notSupportParameterObjectOnNamedArgument() throws NoSuchMethodException {
373 try {
374 Class<?> mapperType = Mapper.class;
375 Method mapperMethod = mapperType.getMethod("getUsersByNameWithParamName", String.class);
376 new ProviderSqlSource(new Configuration(), mapperMethod.getAnnotation(SelectProvider.class), mapperType,
377 mapperMethod).getBoundSql(new Object());
378 fail();
379 } catch (BuilderException e) {
380 assertTrue(e.getMessage().contains(
381 "Error invoking SqlProvider method 'public java.lang.String org.apache.ibatis.submitted.sqlprovider.OurSqlBuilder.buildGetUsersByNameWithParamNameQuery(java.lang.String)' with specify parameter 'class java.lang.Object'. Cause: java.lang.IllegalArgumentException: argument type mismatch"));
382 }
383 }
384
385 @Test
386 void invokeError() throws NoSuchMethodException {
387 try {
388 Class<?> mapperType = ErrorMapper.class;
389 Method mapperMethod = mapperType.getMethod("invokeError");
390 new ProviderSqlSource(new Configuration(), mapperMethod.getAnnotation(SelectProvider.class), mapperType,
391 mapperMethod).getBoundSql(new Object());
392 fail();
393 } catch (BuilderException e) {
394 assertTrue(e.getMessage().contains(
395 "Error invoking SqlProvider method 'public java.lang.String org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorSqlBuilder.invokeError()' with specify parameter 'class java.lang.Object'. Cause: java.lang.UnsupportedOperationException: invokeError"));
396 }
397 }
398
399 @Test
400 void invokeNestedError() throws NoSuchMethodException {
401 try {
402 Class<?> mapperType = ErrorMapper.class;
403 Method mapperMethod = mapperType.getMethod("invokeNestedError");
404 new ProviderSqlSource(new Configuration(), mapperMethod.getAnnotation(SelectProvider.class), mapperType,
405 mapperMethod).getBoundSql(new Object());
406 fail();
407 } catch (BuilderException e) {
408 assertTrue(e.getMessage().contains(
409 "Error invoking SqlProvider method 'public java.lang.String org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorSqlBuilder.invokeNestedError()' with specify parameter 'class java.lang.Object'. Cause: java.lang.UnsupportedOperationException: invokeNestedError"));
410 }
411 }
412
413 @Test
414 void invalidArgumentsCombination() throws NoSuchMethodException {
415 try {
416 Class<?> mapperType = ErrorMapper.class;
417 Method mapperMethod = mapperType.getMethod("invalidArgumentsCombination", String.class);
418 new ProviderSqlSource(new Configuration(), mapperMethod.getAnnotation(DeleteProvider.class), mapperType,
419 mapperMethod).getBoundSql("foo");
420 fail();
421 } catch (BuilderException e) {
422 assertTrue(e.getMessage().contains(
423 "Cannot invoke SqlProvider method 'public java.lang.String org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorSqlBuilder.invalidArgumentsCombination(org.apache.ibatis.builder.annotation.ProviderContext,java.lang.String,java.lang.String)' with specify parameter 'class java.lang.String' because SqlProvider method arguments for 'public abstract void org.apache.ibatis.submitted.sqlprovider.SqlProviderTest$ErrorMapper.invalidArgumentsCombination(java.lang.String)' is an invalid combination."));
424 }
425 }
426
427 @Test
428 void shouldInsertUser() {
429 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
430 Mapper mapper = sqlSession.getMapper(Mapper.class);
431 User user = new User();
432 user.setId(999);
433 user.setName("MyBatis");
434 mapper.insert(user);
435
436 User loadedUser = mapper.getUser(999);
437 assertEquals("MyBatis", loadedUser.getName());
438 }
439 }
440
441 @Test
442 void shouldUpdateUser() {
443 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
444 Mapper mapper = sqlSession.getMapper(Mapper.class);
445 User user = new User();
446 user.setId(999);
447 user.setName("MyBatis");
448 mapper.insert(user);
449
450 user.setName("MyBatis3");
451 mapper.update(user);
452
453 User loadedUser = mapper.getUser(999);
454 assertEquals("MyBatis3", loadedUser.getName());
455 }
456 }
457
458 @Test
459 void shouldDeleteUser() {
460 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
461 Mapper mapper = sqlSession.getMapper(Mapper.class);
462 User user = new User();
463 user.setId(999);
464 user.setName("MyBatis");
465 mapper.insert(user);
466
467 user.setName("MyBatis3");
468 mapper.delete(999);
469
470 User loadedUser = mapper.getUser(999);
471 assertNull(loadedUser);
472 }
473 }
474
475 @Test
476 void mapperProviderContextOnly() {
477 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
478 Mapper mapper = sqlSession.getMapper(Mapper.class);
479 assertEquals("User4", mapper.selectById(4).getName());
480 assertNull(mapper.selectActiveById(4));
481 }
482 }
483
484 @Test
485 void mapperOneParamAndProviderContext() {
486 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
487 Mapper mapper = sqlSession.getMapper(Mapper.class);
488 assertEquals(1, mapper.selectByName("User4").size());
489 assertEquals(0, mapper.selectActiveByName("User4").size());
490 }
491 }
492
493 @Test
494 void mapperMultipleParamAndProviderContextWithAtParam() {
495 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
496 Mapper mapper = sqlSession.getMapper(Mapper.class);
497 assertEquals(1, mapper.selectByIdAndNameWithAtParam(4, "User4").size());
498 assertEquals(0, mapper.selectActiveByIdAndNameWithAtParam(4, "User4").size());
499 }
500 }
501
502 @Test
503 void mapperMultipleParamAndProviderContext() {
504 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
505 Mapper mapper = sqlSession.getMapper(Mapper.class);
506 assertEquals(1, mapper.selectByIdAndName(4, "User4").size());
507 assertEquals(0, mapper.selectActiveByIdAndName(4, "User4").size());
508 }
509 }
510
511 @Test
512 void staticMethodNoArgument() {
513 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
514 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
515 assertEquals(1, mapper.noArgument());
516 }
517 }
518
519 @Test
520 void staticMethodOneArgument() {
521 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
522 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
523 assertEquals(10, mapper.oneArgument(10));
524 }
525 }
526
527 @Test
528 void staticMethodOnePrimitiveByteArgument() {
529 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
530 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
531 assertEquals((byte) 10, mapper.onePrimitiveByteArgument((byte) 10));
532 }
533 }
534
535 @Test
536 void staticMethodOnePrimitiveShortArgument() {
537 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
538 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
539 assertEquals((short) 10, mapper.onePrimitiveShortArgument((short) 10));
540 }
541 }
542
543 @Test
544 void staticMethodOnePrimitiveIntArgument() {
545 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
546 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
547 assertEquals(10, mapper.onePrimitiveIntArgument(10));
548 }
549 }
550
551 @Test
552 void staticMethodOnePrimitiveLongArgument() {
553 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
554 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
555 assertEquals(10L, mapper.onePrimitiveLongArgument(10L));
556 }
557 }
558
559 @Test
560 void staticMethodOnePrimitiveFloatArgument() {
561 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
562 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
563 assertEquals(10.1F, mapper.onePrimitiveFloatArgument(10.1F));
564 }
565 }
566
567 @Test
568 void staticMethodOnePrimitiveDoubleArgument() {
569 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
570 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
571 assertEquals(10.1D, mapper.onePrimitiveDoubleArgument(10.1D));
572 }
573 }
574
575 @Test
576 void staticMethodOnePrimitiveBooleanArgument() {
577 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
578 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
579 assertTrue(mapper.onePrimitiveBooleanArgument(true));
580 }
581 }
582
583 @Test
584 void staticMethodOnePrimitiveCharArgument() {
585 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
586 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
587 assertEquals('A', mapper.onePrimitiveCharArgument('A'));
588 }
589 }
590
591 @Test
592 void boxing() {
593 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
594 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
595 assertEquals(10, mapper.boxing(10));
596 }
597 }
598
599 @Test
600 void unboxing() {
601 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
602 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
603 assertEquals(100, mapper.unboxing(100));
604 }
605 }
606
607 @Test
608 void staticMethodMultipleArgument() {
609 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
610 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
611 assertEquals(2, mapper.multipleArgument(1, 1));
612 }
613 }
614
615 @Test
616 void staticMethodOnlyProviderContext() {
617 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
618 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
619 assertEquals("onlyProviderContext", mapper.onlyProviderContext());
620 }
621 }
622
623 @Test
624 void staticMethodOneArgumentAndProviderContext() {
625 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
626 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
627 assertEquals("oneArgumentAndProviderContext 100", mapper.oneArgumentAndProviderContext(100));
628 }
629 }
630
631 @Test
632 void mapAndProviderContext() {
633 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
634 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
635 assertEquals("mybatis", mapper.mapAndProviderContext("mybatis"));
636 }
637 }
638
639 @Test
640 void multipleMap() {
641 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
642 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
643 assertEquals("123456", mapper.multipleMap(Map.of("value", "123"), Map.of("value", "456")));
644 }
645 }
646
647 @Test
648 void providerContextAndMap() {
649 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
650 StaticMethodSqlProviderMapper mapper = sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
651 assertEquals("mybatis", mapper.providerContextAndParamMap("mybatis"));
652 }
653 }
654
655 @Test
656 @SuppressWarnings("deprecation")
657 void keepBackwardCompatibilityOnDeprecatedConstructorWithAnnotation() throws NoSuchMethodException {
658 Class<?> mapperType = StaticMethodSqlProviderMapper.class;
659 Method mapperMethod = mapperType.getMethod("noArgument");
660 ProviderSqlSource sqlSource = new ProviderSqlSource(new Configuration(),
661 (Object) mapperMethod.getAnnotation(SelectProvider.class), mapperType, mapperMethod);
662 assertEquals("SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS", sqlSource.getBoundSql(null).getSql());
663 }
664
665 @Test
666 void omitTypeWhenSpecifyDefaultType() throws NoSuchMethodException {
667 Class<?> mapperType = DefaultSqlProviderMapper.class;
668 Configuration configuration = new Configuration();
669 configuration.setDefaultSqlProviderType(DefaultSqlProviderMapper.SqlProvider.class);
670 {
671 Method mapperMethod = mapperType.getMethod("select", int.class);
672 String sql = new ProviderSqlSource(configuration, mapperMethod.getAnnotation(SelectProvider.class), mapperType,
673 mapperMethod).getBoundSql(1).getSql();
674 assertEquals("select name from foo where id = ?", sql);
675 }
676 {
677 Method mapperMethod = mapperType.getMethod("insert", String.class);
678 String sql = new ProviderSqlSource(configuration, mapperMethod.getAnnotation(InsertProvider.class), mapperType,
679 mapperMethod).getBoundSql("Taro").getSql();
680 assertEquals("insert into foo (name) values(?)", sql);
681 }
682 {
683 Method mapperMethod = mapperType.getMethod("update", int.class, String.class);
684 String sql = new ProviderSqlSource(configuration, mapperMethod.getAnnotation(UpdateProvider.class), mapperType,
685 mapperMethod).getBoundSql(Collections.emptyMap()).getSql();
686 assertEquals("update foo set name = ? where id = ?", sql);
687 }
688 {
689 Method mapperMethod = mapperType.getMethod("delete", int.class);
690 String sql = new ProviderSqlSource(configuration, mapperMethod.getAnnotation(DeleteProvider.class), mapperType,
691 mapperMethod).getBoundSql(Collections.emptyMap()).getSql();
692 assertEquals("delete from foo where id = ?", sql);
693 }
694 }
695
696 public interface DefaultSqlProviderMapper {
697
698 @SelectProvider
699 String select(int id);
700
701 @InsertProvider
702 void insert(String name);
703
704 @UpdateProvider
705 void update(int id, String name);
706
707 @DeleteProvider
708 void delete(int id);
709
710 final class SqlProvider {
711
712 public static String provideSql(ProviderContext c) {
713 return switch (c.getMapperMethod().getName()) {
714 case "select" -> "select name from foo where id = #{id}";
715 case "insert" -> "insert into foo (name) values(#{name})";
716 case "update" -> "update foo set name = #{name} where id = #{id}";
717 default -> "delete from foo where id = #{id}";
718 };
719 }
720
721 private SqlProvider() {
722 }
723
724 }
725
726 }
727
728 public interface ErrorMapper {
729 @SelectProvider(type = ErrorSqlBuilder.class, method = "methodNotFound")
730 void methodNotFound();
731
732 @SelectProvider(type = ErrorSqlBuilder.class, method = "overload")
733 void methodOverload(String value);
734
735 @SelectProvider(type = ErrorSqlBuilder.class, method = "invokeError")
736 void invokeError();
737
738 @SelectProvider(type = ErrorSqlBuilder.class, method = "invokeNestedError")
739 void invokeNestedError();
740
741 @SelectProvider(type = ErrorSqlBuilder.class, method = "multipleProviderContext")
742 void multipleProviderContext();
743
744 @SelectProvider
745 void omitType();
746
747 @DeleteProvider(value = String.class, type = Integer.class)
748 void differentTypeAndValue();
749
750 @DeleteProvider(type = ErrorSqlBuilder.class, method = "invalidArgumentsCombination")
751 void invalidArgumentsCombination(String value);
752
753 }
754
755 @SuppressWarnings("unused")
756 public static class ErrorSqlBuilder {
757 public void methodNotFound() {
758 throw new UnsupportedOperationException("methodNotFound");
759 }
760
761 public String overload() {
762 throw new UnsupportedOperationException("overload");
763 }
764
765 public String overload(String value) {
766 throw new UnsupportedOperationException("overload");
767 }
768
769 public String invokeError() {
770 throw new UnsupportedOperationException("invokeError");
771 }
772
773 public String invokeNestedError() {
774 throw new IllegalStateException(new UnsupportedOperationException("invokeNestedError"));
775 }
776
777 public String multipleProviderContext(ProviderContext providerContext1, ProviderContext providerContext2) {
778 throw new UnsupportedOperationException("multipleProviderContext");
779 }
780
781 public String invalidArgumentsCombination(ProviderContext providerContext, String value,
782 String unnecessaryArgument) {
783 return "";
784 }
785 }
786
787 public interface StaticMethodSqlProviderMapper {
788 @SelectProvider(type = SqlProvider.class, method = "noArgument")
789 int noArgument();
790
791 @SelectProvider(type = SqlProvider.class, method = "oneArgument")
792 int oneArgument(Integer value);
793
794 @SelectProvider(type = SqlProvider.class, method = "onePrimitiveByteArgument")
795 byte onePrimitiveByteArgument(byte value);
796
797 @SelectProvider(type = SqlProvider.class, method = "onePrimitiveShortArgument")
798 short onePrimitiveShortArgument(short value);
799
800 @SelectProvider(type = SqlProvider.class, method = "onePrimitiveIntArgument")
801 int onePrimitiveIntArgument(int value);
802
803 @SelectProvider(type = SqlProvider.class, method = "onePrimitiveLongArgument")
804 long onePrimitiveLongArgument(long value);
805
806 @SelectProvider(type = SqlProvider.class, method = "onePrimitiveFloatArgument")
807 float onePrimitiveFloatArgument(float value);
808
809 @SelectProvider(type = SqlProvider.class, method = "onePrimitiveDoubleArgument")
810 double onePrimitiveDoubleArgument(double value);
811
812 @SelectProvider(type = SqlProvider.class, method = "onePrimitiveBooleanArgument")
813 boolean onePrimitiveBooleanArgument(boolean value);
814
815 @SelectProvider(type = SqlProvider.class, method = "onePrimitiveCharArgument")
816 char onePrimitiveCharArgument(char value);
817
818 @SelectProvider(type = SqlProvider.class, method = "boxing")
819 int boxing(int value);
820
821 @SelectProvider(type = SqlProvider.class, method = "unboxing")
822 int unboxing(Integer value);
823
824 @SelectProvider(type = SqlProvider.class, method = "multipleArgument")
825 int multipleArgument(@Param("value1") Integer value1, @Param("value2") Integer value2);
826
827 @SelectProvider(type = SqlProvider.class, method = "onlyProviderContext")
828 String onlyProviderContext();
829
830 @SelectProvider(type = SqlProvider.class, method = "oneArgumentAndProviderContext")
831 String oneArgumentAndProviderContext(Integer value);
832
833 @SelectProvider(type = SqlProvider.class, method = "mapAndProviderContext")
834 String mapAndProviderContext(@Param("value") String value);
835
836 @SelectProvider(type = SqlProvider.class, method = "providerContextAndParamMap")
837 String providerContextAndParamMap(@Param("value") String value);
838
839 @SelectProvider(type = SqlProvider.class, method = "multipleMap")
840 String multipleMap(@Param("map1") Map<String, Object> map1, @Param("map2") Map<String, Object> map2);
841
842 @SuppressWarnings("unused")
843 final class SqlProvider {
844
845 public static String noArgument() {
846 return "SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS";
847 }
848
849 public static StringBuilder oneArgument(Integer value) {
850 return new StringBuilder().append("SELECT ").append(value).append(" FROM INFORMATION_SCHEMA.SYSTEM_USERS");
851 }
852
853 public static StringBuilder onePrimitiveByteArgument(byte value) {
854 return new StringBuilder().append("SELECT ").append(value).append(" FROM INFORMATION_SCHEMA.SYSTEM_USERS");
855 }
856
857 public static StringBuilder onePrimitiveShortArgument(short value) {
858 return new StringBuilder().append("SELECT ").append(value).append(" FROM INFORMATION_SCHEMA.SYSTEM_USERS");
859 }
860
861 public static StringBuilder onePrimitiveIntArgument(int value) {
862 return new StringBuilder().append("SELECT ").append(value).append(" FROM INFORMATION_SCHEMA.SYSTEM_USERS");
863 }
864
865 public static StringBuilder onePrimitiveLongArgument(long value) {
866 return new StringBuilder().append("SELECT ").append(value).append(" FROM INFORMATION_SCHEMA.SYSTEM_USERS");
867 }
868
869 public static StringBuilder onePrimitiveFloatArgument(float value) {
870 return new StringBuilder().append("SELECT ").append(value).append(" FROM INFORMATION_SCHEMA.SYSTEM_USERS");
871 }
872
873 public static StringBuilder onePrimitiveDoubleArgument(double value) {
874 return new StringBuilder().append("SELECT ").append(value).append(" FROM INFORMATION_SCHEMA.SYSTEM_USERS");
875 }
876
877 public static StringBuilder onePrimitiveBooleanArgument(boolean value) {
878 return new StringBuilder().append("SELECT ").append(value ? 1 : 0)
879 .append(" FROM INFORMATION_SCHEMA.SYSTEM_USERS");
880 }
881
882 public static StringBuilder onePrimitiveCharArgument(char value) {
883 return new StringBuilder().append("SELECT '").append(value).append("' FROM INFORMATION_SCHEMA.SYSTEM_USERS");
884 }
885
886 public static StringBuilder boxing(Integer value) {
887 return new StringBuilder().append("SELECT '").append(value).append("' FROM INFORMATION_SCHEMA.SYSTEM_USERS");
888 }
889
890 public static StringBuilder unboxing(int value) {
891 return new StringBuilder().append("SELECT '").append(value).append("' FROM INFORMATION_SCHEMA.SYSTEM_USERS");
892 }
893
894 public static CharSequence multipleArgument(@Param("value1") Integer value1, @Param("value2") Integer value2) {
895 return "SELECT " + (value1 + value2) + " FROM INFORMATION_SCHEMA.SYSTEM_USERS";
896 }
897
898 public static CharSequence onlyProviderContext(ProviderContext context) {
899 return new StringBuilder().append("SELECT '").append(context.getMapperMethod().getName())
900 .append("' FROM INFORMATION_SCHEMA.SYSTEM_USERS");
901 }
902
903 public static String oneArgumentAndProviderContext(Integer value, ProviderContext context) {
904 return "SELECT '" + context.getMapperMethod().getName() + " " + value
905 + "' FROM INFORMATION_SCHEMA.SYSTEM_USERS";
906 }
907
908 public static String mapAndProviderContext(Map<String, Object> map, ProviderContext context) {
909 return "SELECT '" + map.get("value") + "' FROM INFORMATION_SCHEMA.SYSTEM_USERS";
910 }
911
912 public static String providerContextAndParamMap(ProviderContext context, MapperMethod.ParamMap<Object> map) {
913 return "SELECT '" + map.get("value") + "' FROM INFORMATION_SCHEMA.SYSTEM_USERS";
914 }
915
916 public static String multipleMap(@Param("map1") Map<String, Object> map1,
917 @Param("map2") Map<String, Object> map2) {
918 return "SELECT '" + map1.get("value") + map2.get("value") + "' FROM INFORMATION_SCHEMA.SYSTEM_USERS";
919 }
920
921 private SqlProvider() {
922 }
923
924 }
925
926 }
927
928 @Test
929 void shouldInsertUserSelective() {
930 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
931 Mapper mapper = sqlSession.getMapper(Mapper.class);
932 User user = new User();
933 user.setId(999);
934 mapper.insertSelective(user);
935
936 User loadedUser = mapper.getUser(999);
937 assertNull(loadedUser.getName());
938 }
939 }
940
941 @Test
942 void shouldUpdateUserSelective() {
943 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
944 Mapper mapper = sqlSession.getMapper(Mapper.class);
945 User user = new User();
946 user.setId(999);
947 user.setName("MyBatis");
948 mapper.insert(user);
949
950 user.setName(null);
951 mapper.updateSelective(user);
952
953 User loadedUser = mapper.getUser(999);
954 assertEquals("MyBatis", loadedUser.getName());
955 }
956 }
957
958 @Test
959 void mapperGetByEntity() {
960 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
961 Mapper mapper = sqlSession.getMapper(Mapper.class);
962 User query = new User();
963 query.setName("User4");
964 assertEquals(1, mapper.getByEntity(query).size());
965 query = new User();
966 query.setId(1);
967 assertEquals(1, mapper.getByEntity(query).size());
968 query = new User();
969 query.setId(1);
970 query.setName("User4");
971 assertEquals(0, mapper.getByEntity(query).size());
972 }
973 }
974
975 @Test
976 void shouldPassedDatabaseIdToProviderMethod() {
977 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
978 DatabaseIdMapper mapper = sqlSession.getMapper(DatabaseIdMapper.class);
979 assertEquals("hsql", mapper.selectDatabaseId());
980 }
981 try (SqlSession sqlSession = sqlSessionFactoryForDerby.openSession()) {
982 DatabaseIdMapper mapper = sqlSession.getMapper(DatabaseIdMapper.class);
983 assertEquals("derby", mapper.selectDatabaseId());
984 }
985 }
986
987 interface DatabaseIdMapper {
988 @SelectProvider(type = SqlProvider.class)
989 String selectDatabaseId();
990
991 @SuppressWarnings("unused")
992 final class SqlProvider {
993 public static String provideSql(ProviderContext context) {
994 if ("hsql".equals(context.getDatabaseId())) {
995 return "SELECT '" + context.getDatabaseId() + "' FROM INFORMATION_SCHEMA.SYSTEM_USERS";
996 }
997 return "SELECT '" + context.getDatabaseId() + "' FROM SYSIBM.SYSDUMMY1";
998 }
999
1000 private SqlProvider() {
1001 }
1002 }
1003 }
1004
1005 }