1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package examples.simple;
17
18 import static examples.simple.AddressDynamicSqlSupport.address;
19 import static examples.simple.PersonDynamicSqlSupport.addressId;
20 import static examples.simple.PersonDynamicSqlSupport.birthDate;
21 import static examples.simple.PersonDynamicSqlSupport.employed;
22 import static examples.simple.PersonDynamicSqlSupport.firstName;
23 import static examples.simple.PersonDynamicSqlSupport.id;
24 import static examples.simple.PersonDynamicSqlSupport.lastName;
25 import static examples.simple.PersonDynamicSqlSupport.occupation;
26 import static examples.simple.PersonDynamicSqlSupport.person;
27 import static org.assertj.core.api.Assertions.assertThat;
28 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
29 import static org.assertj.core.api.Assertions.entry;
30 import static org.mybatis.dynamic.sql.SqlBuilder.*;
31
32 import java.io.InputStream;
33 import java.io.InputStreamReader;
34 import java.sql.Connection;
35 import java.sql.DriverManager;
36 import java.util.Collection;
37 import java.util.Date;
38 import java.util.List;
39 import java.util.Optional;
40
41 import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
42 import org.apache.ibatis.jdbc.ScriptRunner;
43 import org.apache.ibatis.mapping.Environment;
44 import org.apache.ibatis.session.Configuration;
45 import org.apache.ibatis.session.SqlSession;
46 import org.apache.ibatis.session.SqlSessionFactory;
47 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
48 import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
49 import org.junit.jupiter.api.BeforeEach;
50 import org.junit.jupiter.api.Test;
51 import org.mybatis.dynamic.sql.SortSpecification;
52 import org.mybatis.dynamic.sql.delete.DeleteDSLCompleter;
53 import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
54 import org.mybatis.dynamic.sql.exception.NonRenderingWhereClauseException;
55 import org.mybatis.dynamic.sql.insert.render.GeneralInsertStatementProvider;
56 import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
57 import org.mybatis.dynamic.sql.render.RenderingStrategies;
58 import org.mybatis.dynamic.sql.select.CountDSLCompleter;
59 import org.mybatis.dynamic.sql.select.SelectDSLCompleter;
60 import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
61 import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
62
63 class PersonMapperTest {
64
65 private static final String JDBC_URL = "jdbc:hsqldb:mem:aname";
66 private static final String JDBC_DRIVER = "org.hsqldb.jdbcDriver";
67
68 private SqlSessionFactory sqlSessionFactory;
69
70 @BeforeEach
71 void setup() throws Exception {
72 Class.forName(JDBC_DRIVER);
73 try (InputStream is = getClass().getResourceAsStream("/examples/simple/CreateSimpleDB.sql")) {
74 assert is != null;
75 try (Connection connection = DriverManager.getConnection(JDBC_URL, "sa", "");
76 InputStreamReader isr = new InputStreamReader(is)) {
77 ScriptRunner sr = new ScriptRunner(connection);
78 sr.setLogWriter(null);
79 sr.runScript(isr);
80 }
81 }
82
83 UnpooledDataSource ds = new UnpooledDataSource(JDBC_DRIVER, JDBC_URL, "sa", "");
84 Environment environment = new Environment("test", new JdbcTransactionFactory(), ds);
85 Configuration config = new Configuration(environment);
86 config.addMapper(PersonMapper.class);
87 config.addMapper(PersonWithAddressMapper.class);
88 config.addMapper(AddressMapper.class);
89 sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
90 }
91
92 @Test
93 void testSelect() {
94 try (SqlSession session = sqlSessionFactory.openSession()) {
95 PersonMapper mapper = session.getMapper(PersonMapper.class);
96
97 List<PersonRecord> rows = mapper.select(c ->
98 c.where(id, isEqualTo(1))
99 .or(occupation, isNull()));
100
101 assertThat(rows).hasSize(3);
102 }
103 }
104
105 @Test
106 void testSelectEmployed() {
107 try (SqlSession session = sqlSessionFactory.openSession()) {
108 PersonMapper mapper = session.getMapper(PersonMapper.class);
109
110 List<PersonRecord> rows = mapper.select(c ->
111 c.where(employed, isTrue())
112 .orderBy(id));
113
114 assertThat(rows).hasSize(4);
115 assertThat(rows.get(0).id()).isEqualTo(1);
116 }
117 }
118
119 @Test
120 void testSelectUnemployed() {
121 try (SqlSession session = sqlSessionFactory.openSession()) {
122 PersonMapper mapper = session.getMapper(PersonMapper.class);
123
124 List<PersonRecord> rows = mapper.select(c ->
125 c.where(employed, isFalse())
126 .orderBy(id));
127
128 assertThat(rows).hasSize(2);
129 assertThat(rows.get(0).id()).isEqualTo(3);
130 }
131 }
132
133 @Test
134 void testSelectWithTypeConversion() throws NumberFormatException {
135 try (SqlSession session = sqlSessionFactory.openSession()) {
136 PersonMapper mapper = session.getMapper(PersonMapper.class);
137
138 List<PersonRecord> rows = mapper.select(c ->
139 c.where(id, isEqualTo("1").map(Integer::parseInt))
140 .or(occupation, isNull()));
141
142 assertThat(rows).hasSize(3);
143 }
144 }
145
146 @Test
147 void testSelectWithTypeConversionAndFilterAndNull() throws NumberFormatException {
148 try (SqlSession session = sqlSessionFactory.openSession()) {
149 PersonMapper mapper = session.getMapper(PersonMapper.class);
150
151 List<PersonRecord> rows = mapper.select(c ->
152 c.where(id, isEqualToWhenPresent((String) null).map(Integer::parseInt))
153 .or(occupation, isNull()));
154
155 assertThat(rows).hasSize(2);
156 }
157 }
158
159
160 @Test
161 void testGeneralSelect() {
162 try (SqlSession session = sqlSessionFactory.openSession()) {
163 PersonMapper mapper = session.getMapper(PersonMapper.class);
164
165 SelectStatementProvider selectStatement = select(id.as("A_ID"), firstName, lastName, birthDate, employed,
166 occupation, addressId)
167 .from(person)
168 .where(id, isEqualTo(1))
169 .or(occupation, isNull())
170 .build()
171 .render(RenderingStrategies.MYBATIS3);
172
173 List<PersonRecord> rows = mapper.selectMany(selectStatement);
174 assertThat(rows).hasSize(3);
175 }
176 }
177
178 @Test
179 void testSelectAll() {
180 try (SqlSession session = sqlSessionFactory.openSession()) {
181 PersonMapper mapper = session.getMapper(PersonMapper.class);
182
183 List<PersonRecord> rows = mapper.select(SelectDSLCompleter.allRows());
184
185 assertThat(rows).hasSize(6);
186 assertThat(rows.get(0).id()).isEqualTo(1);
187 assertThat(rows.get(5).id()).isEqualTo(6);
188 }
189 }
190
191 @Test
192 void testSelectAllOrdered() {
193 try (SqlSession session = sqlSessionFactory.openSession()) {
194 PersonMapper mapper = session.getMapper(PersonMapper.class);
195
196 List<PersonRecord> rows = mapper
197 .select(SelectDSLCompleter.allRowsOrderedBy(lastName.descending(), firstName.descending()));
198
199 assertThat(rows).hasSize(6);
200 assertThat(rows.get(0).id()).isEqualTo(5);
201 assertThat(rows.get(5).id()).isEqualTo(1);
202 }
203 }
204
205 @Test
206 void testSelectDistinct() {
207 try (SqlSession session = sqlSessionFactory.openSession()) {
208 PersonMapper mapper = session.getMapper(PersonMapper.class);
209
210 List<PersonRecord> rows = mapper.selectDistinct(c ->
211 c.where(id, isGreaterThan(1))
212 .or(occupation, isNull()));
213
214 assertThat(rows).hasSize(5);
215 }
216 }
217
218 @Test
219 void testSelectWithTypeHandler() {
220 try (SqlSession session = sqlSessionFactory.openSession()) {
221 PersonMapper mapper = session.getMapper(PersonMapper.class);
222
223 List<PersonRecord> rows = mapper.select(c ->
224 c.where(employed, isEqualTo(false))
225 .orderBy(id));
226
227 assertThat(rows).hasSize(2);
228 assertThat(rows.get(0).id()).isEqualTo(3);
229 assertThat(rows.get(1).id()).isEqualTo(6);
230 }
231 }
232
233 @Test
234 void testSelectByPrimaryKeyWithMissingRecord() {
235 try (SqlSession session = sqlSessionFactory.openSession()) {
236 PersonMapper mapper = session.getMapper(PersonMapper.class);
237
238 Optional<PersonRecord> row = mapper.selectByPrimaryKey(300);
239 assertThat(row).isNotPresent();
240 }
241 }
242
243 @Test
244 void testFirstNameIn() {
245 try (SqlSession session = sqlSessionFactory.openSession()) {
246 PersonMapper mapper = session.getMapper(PersonMapper.class);
247
248 List<PersonRecord> rows = mapper.select(c ->
249 c.where(firstName, isIn("Fred", "Barney")));
250
251 assertThat(rows).hasSize(2);
252 assertThat(rows.get(0))
253 .isNotNull()
254 .extracting("lastName").isNotNull()
255 .extracting("name").isEqualTo("Flintstone");
256 assertThat(rows.get(1))
257 .isNotNull()
258 .extracting("lastName").isNotNull()
259 .extracting("name").isEqualTo("Rubble");
260 }
261 }
262
263 @Test
264 void testOrderByCollection() {
265 Collection<SortSpecification> orderByColumns = List.of(firstName);
266
267 try (SqlSession session = sqlSessionFactory.openSession()) {
268 PersonMapper mapper = session.getMapper(PersonMapper.class);
269
270 List<PersonRecord> rows = mapper.select(c -> c
271 .where(firstName, isIn("Fred", "Barney"))
272 .orderBy(orderByColumns)
273 );
274
275 assertThat(rows).hasSize(2);
276 assertThat(rows.get(0))
277 .isNotNull()
278 .extracting("lastName").isNotNull()
279 .extracting("name").isEqualTo("Rubble");
280 assertThat(rows.get(1))
281 .isNotNull()
282 .extracting("lastName").isNotNull()
283 .extracting("name").isEqualTo("Flintstone");
284 }
285 }
286
287 @Test
288 void testDelete() {
289 try (SqlSession session = sqlSessionFactory.openSession()) {
290 PersonMapper mapper = session.getMapper(PersonMapper.class);
291 int rows = mapper.delete(c ->
292 c.where(occupation, isNull()));
293 assertThat(rows).isEqualTo(2);
294 }
295 }
296
297
298 @Test
299 void testGeneralDelete() {
300 try (SqlSession session = sqlSessionFactory.openSession()) {
301 PersonMapper mapper = session.getMapper(PersonMapper.class);
302
303 DeleteStatementProvider deleteStatement = deleteFrom(person)
304 .where(occupation, isNull())
305 .build()
306 .render(RenderingStrategies.MYBATIS3);
307
308 int rows = mapper.delete(deleteStatement);
309 assertThat(rows).isEqualTo(2);
310 }
311 }
312
313 @Test
314 void testDeleteAll() {
315 try (SqlSession session = sqlSessionFactory.openSession()) {
316 PersonMapper mapper = session.getMapper(PersonMapper.class);
317 int rows = mapper.delete(DeleteDSLCompleter.allRows());
318
319 assertThat(rows).isEqualTo(6);
320 }
321 }
322
323 @Test
324 void testDeleteByPrimaryKey() {
325 try (SqlSession session = sqlSessionFactory.openSession()) {
326 PersonMapper mapper = session.getMapper(PersonMapper.class);
327 int rows = mapper.deleteByPrimaryKey(2);
328
329 assertThat(rows).isEqualTo(1);
330 }
331 }
332
333 @Test
334 void testInsert() {
335 try (SqlSession session = sqlSessionFactory.openSession()) {
336 PersonMapper mapper = session.getMapper(PersonMapper.class);
337 PersonRecord row = new PersonRecord(100, "Joe", new LastName("Jones"), new Date(), true, "Developer", 1);
338
339 int rows = mapper.insert(row);
340 assertThat(rows).isEqualTo(1);
341 }
342 }
343
344 @Test
345 void testRawInsert() {
346 try (SqlSession session = sqlSessionFactory.openSession()) {
347 PersonMapper mapper = session.getMapper(PersonMapper.class);
348 PersonRecord row = new PersonRecord(100, "Joe", new LastName("Jones"), new Date(), true, "Developer", 1);
349
350 InsertStatementProvider<PersonRecord> insertStatement = insert(row).into(person)
351 .withMappedColumn(id)
352 .withMappedColumn(firstName)
353 .withMappedColumn(lastName)
354 .withMappedColumn(birthDate)
355 .withMappedColumn(employed)
356 .withMappedColumn(occupation)
357 .withMappedColumn(addressId)
358 .build().render(RenderingStrategies.MYBATIS3);
359
360 int rows = mapper.insert(insertStatement);
361 assertThat(rows).isEqualTo(1);
362 }
363 }
364
365 @Test
366 void testGeneralInsert() {
367 try (SqlSession session = sqlSessionFactory.openSession()) {
368 PersonMapper mapper = session.getMapper(PersonMapper.class);
369 int rows = mapper.generalInsert(c ->
370 c.set(id).toValue(100)
371 .set(firstName).toValue("Joe")
372 .set(lastName).toValue(new LastName("Jones"))
373 .set(birthDate).toValue(new Date())
374 .set(employed).toValue(true)
375 .set(occupation).toValue("Developer")
376 .set(addressId).toValue(1)
377 );
378
379 assertThat(rows).isEqualTo(1);
380 }
381 }
382
383 @Test
384 void testInsertMultiple() {
385 try (SqlSession session = sqlSessionFactory.openSession()) {
386 PersonMapper mapper = session.getMapper(PersonMapper.class);
387
388 List<PersonRecord> records = List.of(
389 new PersonRecord(100, "Joe", new LastName("Jones"), new Date(), true, "Developer", 1),
390 new PersonRecord(101, "Sarah", new LastName("Smith"), new Date(), true, "Architect", 2)
391 );
392
393 int rows = mapper.insertMultiple(records);
394 assertThat(rows).isEqualTo(2);
395 }
396 }
397
398 @Test
399 void testInsertSelective() {
400 try (SqlSession session = sqlSessionFactory.openSession()) {
401 PersonMapper mapper = session.getMapper(PersonMapper.class);
402 PersonRecord row = new PersonRecord(100, "Joe", new LastName("Jones"), new Date(), false, null, 1);
403
404 int rows = mapper.insertSelective(row);
405 assertThat(rows).isEqualTo(1);
406 }
407 }
408
409 @Test
410 void testUpdateByPrimaryKeyNullKeyShouldThrowException() {
411 try (SqlSession session = sqlSessionFactory.openSession()) {
412 PersonMapper mapper = session.getMapper(PersonMapper.class);
413 PersonRecord row = new PersonRecord(null, "Joe", new LastName("Jones"), new Date(), true, "Developer", 1);
414
415 assertThatExceptionOfType(NonRenderingWhereClauseException.class).isThrownBy(() -> mapper.updateByPrimaryKey(row));
416 }
417 }
418
419 @Test
420 void testUpdateByPrimaryKey() {
421 try (SqlSession session = sqlSessionFactory.openSession()) {
422 PersonMapper mapper = session.getMapper(PersonMapper.class);
423 PersonRecord row = new PersonRecord(100, "Joe", new LastName("Jones"), new Date(), true, "Developer", 1);
424
425 int rows = mapper.insert(row);
426 assertThat(rows).isEqualTo(1);
427
428 row = row.withOccupation("Programmer");
429 rows = mapper.updateByPrimaryKey(row);
430 assertThat(rows).isEqualTo(1);
431
432 Optional<PersonRecord> newRecord = mapper.selectByPrimaryKey(100);
433 assertThat(newRecord).hasValueSatisfying(r ->
434 assertThat(r.occupation()).isEqualTo("Programmer"));
435 }
436 }
437
438 @Test
439 void testUpdateByPrimaryKeySelective() {
440 try (SqlSession session = sqlSessionFactory.openSession()) {
441 PersonMapper mapper = session.getMapper(PersonMapper.class);
442 PersonRecord row = new PersonRecord(100, "Joe", new LastName("Jones"), new Date(), true, "Developer", 1);
443
444 int rows = mapper.insert(row);
445 assertThat(rows).isEqualTo(1);
446
447 PersonRecord updateRecord = new PersonRecord(100, null, null, null, null, "Programmer", null);
448 rows = mapper.updateByPrimaryKeySelective(updateRecord);
449 assertThat(rows).isEqualTo(1);
450
451 Optional<PersonRecord> newRecord = mapper.selectByPrimaryKey(100);
452 assertThat(newRecord).hasValueSatisfying(r -> {
453 assertThat(r.occupation()).isEqualTo("Programmer");
454 assertThat(r.firstName()).isEqualTo("Joe");
455 });
456 }
457 }
458
459 @Test
460 void testUpdate() {
461 try (SqlSession session = sqlSessionFactory.openSession()) {
462 PersonMapper mapper = session.getMapper(PersonMapper.class);
463 PersonRecord row = new PersonRecord(100, "Joe", new LastName("Jones"), new Date(), true, "Developer", 1);
464
465 int rows = mapper.insert(row);
466 assertThat(rows).isEqualTo(1);
467
468 PersonRecord updateRow = row.withOccupation("Programmer");
469
470 rows = mapper.update(c ->
471 PersonMapper.updateAllColumns(updateRow, c)
472 .where(id, isEqualTo(100))
473 .and(firstName, isEqualTo("Joe")));
474
475 assertThat(rows).isEqualTo(1);
476
477 Optional<PersonRecord> newRecord = mapper.selectByPrimaryKey(100);
478 assertThat(newRecord).hasValueSatisfying(r ->
479 assertThat(r.occupation()).isEqualTo("Programmer"));
480 }
481 }
482
483 @Test
484 void testUpdateOneField() {
485 try (SqlSession session = sqlSessionFactory.openSession()) {
486 PersonMapper mapper = session.getMapper(PersonMapper.class);
487 PersonRecord row = new PersonRecord(100, "Joe", new LastName("Jones"), new Date(), true, "Developer", 1);
488
489 int rows = mapper.insert(row);
490 assertThat(rows).isEqualTo(1);
491
492 rows = mapper.update(c ->
493 c.set(occupation).equalTo("Programmer")
494 .where(id, isEqualTo(100)));
495
496 assertThat(rows).isEqualTo(1);
497
498 Optional<PersonRecord> newRecord = mapper.selectByPrimaryKey(100);
499 assertThat(newRecord).hasValueSatisfying(r ->
500 assertThat(r.occupation()).isEqualTo("Programmer"));
501 }
502 }
503
504 @Test
505 void testUpdateAll() {
506 try (SqlSession session = sqlSessionFactory.openSession()) {
507 PersonMapper mapper = session.getMapper(PersonMapper.class);
508 PersonRecord row = new PersonRecord(100, "Joe", new LastName("Jones"), new Date(), true, "Developer", 1);
509
510 int rows = mapper.insert(row);
511 assertThat(rows).isEqualTo(1);
512
513 PersonRecord updateRecord = new PersonRecord(null, null, null, null, null, "Programmer", null);
514 rows = mapper.update(c ->
515 PersonMapper.updateSelectiveColumns(updateRecord, c));
516
517 assertThat(rows).isEqualTo(7);
518
519 Optional<PersonRecord> newRecord = mapper.selectByPrimaryKey(100);
520 assertThat(newRecord).hasValueSatisfying(r ->
521 assertThat(r.occupation()).isEqualTo("Programmer"));
522 }
523 }
524
525 @Test
526 void testUpdateSelective() {
527 try (SqlSession session = sqlSessionFactory.openSession()) {
528 PersonMapper mapper = session.getMapper(PersonMapper.class);
529 PersonRecord row = new PersonRecord(100, "Joe", new LastName("Jones"), new Date(), true, "Developer", 1);
530
531 int rows = mapper.insert(row);
532 assertThat(rows).isEqualTo(1);
533
534 PersonRecord updateRecord = new PersonRecord(null, null, null, null, null, "Programmer", null);
535 rows = mapper.update(c ->
536 PersonMapper.updateSelectiveColumns(updateRecord, c)
537 .where(id, isEqualTo(100)));
538
539 assertThat(rows).isEqualTo(1);
540
541 Optional<PersonRecord> newRecord = mapper.selectByPrimaryKey(100);
542 assertThat(newRecord).hasValueSatisfying(r ->
543 assertThat(r.occupation()).isEqualTo("Programmer"));
544 }
545 }
546
547 @Test
548 void testCount() {
549 try (SqlSession session = sqlSessionFactory.openSession()) {
550 PersonMapper mapper = session.getMapper(PersonMapper.class);
551 long rows = mapper.count(c ->
552 c.where(occupation, isNull()));
553
554 assertThat(rows).isEqualTo(2L);
555 }
556 }
557
558 @Test
559 void testCountAll() {
560 try (SqlSession session = sqlSessionFactory.openSession()) {
561 PersonMapper mapper = session.getMapper(PersonMapper.class);
562 long rows = mapper.count(CountDSLCompleter.allRows());
563
564 assertThat(rows).isEqualTo(6L);
565 }
566 }
567
568 @Test
569 void testCountLastName() {
570 try (SqlSession session = sqlSessionFactory.openSession()) {
571 PersonMapper mapper = session.getMapper(PersonMapper.class);
572 long rows = mapper.count(lastName, CountDSLCompleter.allRows());
573
574 assertThat(rows).isEqualTo(6L);
575 }
576 }
577
578 @Test
579 void testCountDistinctLastName() {
580 try (SqlSession session = sqlSessionFactory.openSession()) {
581 PersonMapper mapper = session.getMapper(PersonMapper.class);
582 long rows = mapper.countDistinct(lastName, CountDSLCompleter.allRows());
583
584 assertThat(rows).isEqualTo(2L);
585 }
586 }
587
588 @Test
589 void testTypeHandledLike() {
590 try (SqlSession session = sqlSessionFactory.openSession()) {
591 PersonMapper mapper = session.getMapper(PersonMapper.class);
592
593 List<PersonRecord> rows = mapper.select(c ->
594 c.where(lastName, isLike(new LastName("Fl%")))
595 .orderBy(id));
596
597 assertThat(rows).hasSize(3);
598 assertThat(rows.get(0).firstName()).isEqualTo("Fred");
599 }
600 }
601
602 @Test
603 void testTypeHandledNotLike() {
604 try (SqlSession session = sqlSessionFactory.openSession()) {
605 PersonMapper mapper = session.getMapper(PersonMapper.class);
606
607 List<PersonRecord> rows = mapper.select(c ->
608 c.where(lastName, isNotLike(new LastName("Fl%")))
609 .orderBy(id));
610
611 assertThat(rows).hasSize(3);
612 assertThat(rows.get(0).firstName()).isEqualTo("Barney");
613 }
614 }
615
616 @Test
617 void testJoinAllRows() {
618 try (SqlSession session = sqlSessionFactory.openSession()) {
619 PersonWithAddressMapper mapper = session.getMapper(PersonWithAddressMapper.class);
620 List<PersonWithAddress> records = mapper.select(
621 SelectDSLCompleter.allRowsOrderedBy(id)
622 );
623
624 assertThat(records).hasSize(6);
625 assertThat(records.get(0).getId()).isEqualTo(1);
626 assertThat(records.get(0).getEmployed()).isTrue();
627 assertThat(records.get(0).getFirstName()).isEqualTo("Fred");
628 assertThat(records.get(0).getLastName()).isEqualTo(new LastName("Flintstone"));
629 assertThat(records.get(0).getOccupation()).isEqualTo("Brontosaurus Operator");
630 assertThat(records.get(0).getBirthDate()).isNotNull();
631 assertThat(records.get(0).getAddress()).isNotNull()
632 .extracting("id", "streetAddress", "city", "state", "addressType")
633 .containsExactly(1, "123 Main Street", "Bedrock", "IN", AddressRecord.AddressType.HOME);
634
635 assertThat(records.get(4).getAddress()).isNotNull()
636 .extracting("addressType")
637 .isEqualTo(AddressRecord.AddressType.BUSINESS);
638 }
639 }
640
641 @Test
642 void testJoinOneRow() {
643 try (SqlSession session = sqlSessionFactory.openSession()) {
644 PersonWithAddressMapper mapper = session.getMapper(PersonWithAddressMapper.class);
645 List<PersonWithAddress> records = mapper.select(c -> c.where(id, isEqualTo(1)));
646
647 assertThat(records).hasSize(1);
648 assertThat(records.get(0).getId()).isEqualTo(1);
649 assertThat(records.get(0).getEmployed()).isTrue();
650 assertThat(records.get(0).getFirstName()).isEqualTo("Fred");
651 assertThat(records.get(0).getLastName()).isEqualTo(new LastName("Flintstone"));
652 assertThat(records.get(0).getOccupation()).isEqualTo("Brontosaurus Operator");
653 assertThat(records.get(0).getBirthDate()).isNotNull();
654 assertThat(records.get(0).getAddress()).isNotNull()
655 .extracting("id", "streetAddress", "city", "state", "addressType")
656 .containsExactly(1, "123 Main Street", "Bedrock", "IN", AddressRecord.AddressType.HOME);
657 }
658 }
659
660 @Test
661 void testJoinPrimaryKey() {
662 try (SqlSession session = sqlSessionFactory.openSession()) {
663 PersonWithAddressMapper mapper = session.getMapper(PersonWithAddressMapper.class);
664 Optional<PersonWithAddress> row = mapper.selectByPrimaryKey(1);
665
666 assertThat(row).hasValueSatisfying(r -> {
667 assertThat(r.getId()).isEqualTo(1);
668 assertThat(r.getEmployed()).isTrue();
669 assertThat(r.getFirstName()).isEqualTo("Fred");
670 assertThat(r.getLastName()).isEqualTo(new LastName("Flintstone"));
671 assertThat(r.getOccupation()).isEqualTo("Brontosaurus Operator");
672 assertThat(r.getBirthDate()).isNotNull();
673 assertThat(r.getAddress()).isNotNull()
674 .extracting("id", "streetAddress", "city", "state", "addressType")
675 .containsExactly(1, "123 Main Street", "Bedrock", "IN", AddressRecord.AddressType.HOME);
676 });
677 }
678 }
679
680 @Test
681 void testJoinPrimaryKeyInvalidRecord() {
682 try (SqlSession session = sqlSessionFactory.openSession()) {
683 PersonWithAddressMapper mapper = session.getMapper(PersonWithAddressMapper.class);
684 Optional<PersonWithAddress> row = mapper.selectByPrimaryKey(55);
685
686 assertThat(row).isEmpty();
687 }
688 }
689
690 @Test
691 void testJoinCount() {
692 try (SqlSession session = sqlSessionFactory.openSession()) {
693 PersonWithAddressMapper mapper = session.getMapper(PersonWithAddressMapper.class);
694 long count = mapper.count(c -> c.where(person.id, isEqualTo(55)));
695
696 assertThat(count).isZero();
697 }
698 }
699
700 @Test
701 void testJoinCountWithSubcriteria() {
702 try (SqlSession session = sqlSessionFactory.openSession()) {
703 PersonWithAddressMapper mapper = session.getMapper(PersonWithAddressMapper.class);
704 long count = mapper.count(c -> c.where(person.id, isEqualTo(55), or(person.id, isEqualTo(1))));
705
706 assertThat(count).isEqualTo(1);
707 }
708 }
709
710 @Test
711 void testJoinCountWithSubcriteriaInSingleStatement() {
712 try (SqlSession session = sqlSessionFactory.openSession()) {
713 PersonWithAddressMapper mapper = session.getMapper(PersonWithAddressMapper.class);
714
715 SelectStatementProvider selectStatement = countFrom(person)
716 .join(address).on(person.id, isEqualTo(address.id))
717 .where(person.id, isEqualTo(55), or(person.id, isEqualTo(1)))
718 .build()
719 .render(RenderingStrategies.MYBATIS3);
720
721 String expected = """
722 select count(*)
723 from Person
724 join Address on Person.id = Address.address_id
725 where Person.id = #{parameters.p1,jdbcType=INTEGER} or Person.id = #{parameters.p2,jdbcType=INTEGER}
726 """;
727 assertThat(selectStatement.getSelectStatement()).isEqualToNormalizingWhitespace(expected);
728
729 long count = mapper.count(selectStatement);
730 assertThat(count).isEqualTo(1);
731 }
732 }
733
734 @Test
735 void testJoinCountInSingleStatement() {
736 try (SqlSession session = sqlSessionFactory.openSession()) {
737 PersonWithAddressMapper mapper = session.getMapper(PersonWithAddressMapper.class);
738
739 SelectStatementProvider selectStatement = countFrom(person, "p")
740 .join(address, "a").on(person.id, isEqualTo(address.id))
741 .configureStatement(c -> c.setNonRenderingWhereClauseAllowed(true))
742 .build()
743 .render(RenderingStrategies.MYBATIS3);
744
745 String expected = """
746 select count(*)
747 from Person p
748 join Address a on p.id = a.address_id
749 """;
750 assertThat(selectStatement.getSelectStatement()).isEqualToNormalizingWhitespace(expected);
751
752 long count = mapper.count(selectStatement);
753 assertThat(count).isEqualTo(2);
754 }
755 }
756
757 @Test
758 void testSelectJoinForUpdate() {
759 SelectStatementProvider selectStatement = select(person.id, address.city)
760 .from(person, "p")
761 .join(address, "a").on(person.id, isEqualTo(address.id))
762 .forUpdate()
763 .build()
764 .render(RenderingStrategies.MYBATIS3);
765
766 String expected = """
767 select p.id, a.city
768 from Person p
769 join Address a on p.id = a.address_id
770 for update
771 """;
772 assertThat(selectStatement.getSelectStatement()).isEqualToNormalizingWhitespace(expected);
773 }
774
775 @Test
776 void testWithEnumOrdinalTypeHandler() {
777 try (SqlSession session = sqlSessionFactory.openSession()) {
778 AddressMapper mapper = session.getMapper(AddressMapper.class);
779
780 GeneralInsertStatementProvider insertStatement = insertInto(address)
781 .set(address.id).toValue(4)
782 .set(address.streetAddress).toValue("987 Elm Street")
783 .set(address.city).toValue("Mayberry")
784 .set(address.state).toValue("NC")
785 .set(address.addressType).toValue(AddressRecord.AddressType.HOME)
786 .build()
787 .render(RenderingStrategies.MYBATIS3);
788
789 int rows = mapper.generalInsert(insertStatement);
790 assertThat(rows).isEqualTo(1);
791
792 SelectStatementProvider selectStatement = select(address.addressType)
793 .from(address)
794 .where(address.id, isEqualTo(4))
795 .build()
796 .render(RenderingStrategies.MYBATIS3);
797
798 Optional<Integer> type = mapper.selectOptionalInteger(selectStatement);
799 assertThat(type).hasValueSatisfying(i -> assertThat(i).isZero());
800 }
801 }
802
803 @Test
804 void testMultiSelectWithUnion() {
805 try (SqlSession session = sqlSessionFactory.openSession()) {
806 PersonMapper mapper = session.getMapper(PersonMapper.class);
807
808 SelectStatementProvider selectStatement = multiSelect(
809 select(id.as("A_ID"), firstName, lastName, birthDate, employed, occupation, addressId)
810 .from(person)
811 .where(id, isLessThanOrEqualTo(2))
812 .orderBy(id)
813 .limit(1)
814 ).union(
815 select(id.as("A_ID"), firstName, lastName, birthDate, employed, occupation, addressId)
816 .from(person)
817 .where(id, isGreaterThanOrEqualTo(4))
818 .orderBy(id.descending())
819 .limit(1)
820 )
821 .orderBy(sortColumn("A_ID"))
822 .limit(3)
823 .build()
824 .render(RenderingStrategies.MYBATIS3);
825
826 String expected =
827 "(select id as A_ID, first_name, last_name, birth_date, employed, occupation, address_id " +
828 "from Person " +
829 "where id <= #{parameters.p1,jdbcType=INTEGER} " +
830 "order by id limit #{parameters.p2}) " +
831 "union " +
832 "(select id as A_ID, first_name, last_name, birth_date, employed, occupation, address_id " +
833 "from Person " +
834 "where id >= #{parameters.p3,jdbcType=INTEGER} " +
835 "order by id DESC limit #{parameters.p4}) " +
836 "order by A_ID " +
837 "limit #{parameters.p5}";
838
839 assertThat(selectStatement.getSelectStatement()).isEqualTo(expected);
840
841 List<PersonRecord> records = mapper.selectMany(selectStatement);
842
843 assertThat(records).hasSize(2);
844 assertThat(records.get(0).id()).isEqualTo(1);
845 assertThat(records.get(1).id()).isEqualTo(6);
846 }
847 }
848
849 @Test
850 void testMultiSelectWithUnionAll() {
851 try (SqlSession session = sqlSessionFactory.openSession()) {
852 PersonMapper mapper = session.getMapper(PersonMapper.class);
853
854 SelectStatementProvider selectStatement = multiSelect(
855 select(id.as("A_ID"), firstName, lastName, birthDate, employed, occupation, addressId)
856 .from(person)
857 .where(id, isLessThanOrEqualTo(2))
858 .orderBy(id)
859 .limit(1)
860 ).unionAll(
861 select(id.as("A_ID"), firstName, lastName, birthDate, employed, occupation, addressId)
862 .from(person)
863 .where(id, isGreaterThanOrEqualTo(4))
864 .orderBy(id.descending())
865 .limit(1)
866 ).orderBy(sortColumn("A_ID"))
867 .fetchFirst(2).rowsOnly()
868 .build()
869 .render(RenderingStrategies.MYBATIS3);
870
871 String expected =
872 "(select id as A_ID, first_name, last_name, birth_date, employed, occupation, address_id " +
873 "from Person " +
874 "where id <= #{parameters.p1,jdbcType=INTEGER} " +
875 "order by id limit #{parameters.p2}) " +
876 "union all " +
877 "(select id as A_ID, first_name, last_name, birth_date, employed, occupation, address_id " +
878 "from Person " +
879 "where id >= #{parameters.p3,jdbcType=INTEGER} " +
880 "order by id DESC limit #{parameters.p4}) " +
881 "order by A_ID " +
882 "fetch first #{parameters.p5} rows only";
883
884 assertThat(selectStatement.getSelectStatement()).isEqualTo(expected);
885
886 List<PersonRecord> records = mapper.selectMany(selectStatement);
887
888 assertThat(records).hasSize(2);
889 assertThat(records.get(0).id()).isEqualTo(1);
890 assertThat(records.get(1).id()).isEqualTo(6);
891 }
892 }
893
894 @Test
895 void testMultiSelectPagingVariation1() {
896 SelectStatementProvider selectStatement = multiSelect(
897 select(id, firstName, lastName, birthDate, employed, occupation, addressId)
898 .from(person)
899 .where(id, isLessThanOrEqualTo(2))
900 ).unionAll(
901 select(id, firstName, lastName, birthDate, employed, occupation, addressId)
902 .from(person)
903 .where(id, isGreaterThanOrEqualTo(4))
904 )
905 .orderBy(id)
906 .limit(3).offset(2)
907 .build()
908 .render(RenderingStrategies.MYBATIS3);
909
910 String expected =
911 "(select id, first_name, last_name, birth_date, employed, occupation, address_id " +
912 "from Person " +
913 "where id <= #{parameters.p1,jdbcType=INTEGER}) " +
914 "union all " +
915 "(select id, first_name, last_name, birth_date, employed, occupation, address_id " +
916 "from Person " +
917 "where id >= #{parameters.p2,jdbcType=INTEGER}) " +
918 "order by id " +
919 "limit #{parameters.p3} offset #{parameters.p4}";
920
921 assertThat(selectStatement.getSelectStatement()).isEqualTo(expected);
922 }
923
924 @Test
925 void testMultiSelectPagingVariation2() {
926 SelectStatementProvider selectStatement = multiSelect(
927 select(id, firstName, lastName, birthDate, employed, occupation, addressId)
928 .from(person)
929 .where(id, isLessThanOrEqualTo(2))
930 ).unionAll(
931 select(id, firstName, lastName, birthDate, employed, occupation, addressId)
932 .from(person)
933 .where(id, isGreaterThanOrEqualTo(4))
934 )
935 .orderBy(id)
936 .offset(2)
937 .build()
938 .render(RenderingStrategies.MYBATIS3);
939
940 String expected =
941 "(select id, first_name, last_name, birth_date, employed, occupation, address_id " +
942 "from Person " +
943 "where id <= #{parameters.p1,jdbcType=INTEGER}) " +
944 "union all " +
945 "(select id, first_name, last_name, birth_date, employed, occupation, address_id " +
946 "from Person " +
947 "where id >= #{parameters.p2,jdbcType=INTEGER}) " +
948 "order by id " +
949 "offset #{parameters.p3} rows";
950
951 assertThat(selectStatement.getSelectStatement()).isEqualTo(expected);
952 }
953
954 @Test
955 void testMultiSelectPagingVariation3() {
956 SelectStatementProvider selectStatement = multiSelect(
957 select(id, firstName, lastName, birthDate, employed, occupation, addressId)
958 .from(person)
959 .where(id, isLessThanOrEqualTo(2))
960 ).unionAll(
961 select(id, firstName, lastName, birthDate, employed, occupation, addressId)
962 .from(person)
963 .where(id, isGreaterThanOrEqualTo(4))
964 )
965 .orderBy(id)
966 .offset(2).fetchFirst(3).rowsOnly()
967 .build()
968 .render(RenderingStrategies.MYBATIS3);
969
970 String expected =
971 "(select id, first_name, last_name, birth_date, employed, occupation, address_id " +
972 "from Person " +
973 "where id <= #{parameters.p1,jdbcType=INTEGER}) " +
974 "union all " +
975 "(select id, first_name, last_name, birth_date, employed, occupation, address_id " +
976 "from Person " +
977 "where id >= #{parameters.p2,jdbcType=INTEGER}) " +
978 "order by id " +
979 "offset #{parameters.p3} rows fetch first #{parameters.p4} rows only";
980
981 assertThat(selectStatement.getSelectStatement()).isEqualTo(expected);
982 }
983
984 @Test
985 void testMultiSelectPagingVariation() {
986 SelectStatementProvider selectStatement = multiSelect(
987 select(id, firstName, lastName, birthDate, employed, occupation, addressId)
988 .from(person)
989 .where(id, isLessThanOrEqualTo(2))
990 ).unionAll(
991 select(id, firstName, lastName, birthDate, employed, occupation, addressId)
992 .from(person)
993 .where(id, isGreaterThanOrEqualTo(4))
994 )
995 .orderBy(id)
996 .build()
997 .render(RenderingStrategies.MYBATIS3);
998
999 String expected =
1000 "(select id, first_name, last_name, birth_date, employed, occupation, address_id " +
1001 "from Person " +
1002 "where id <= #{parameters.p1,jdbcType=INTEGER}) " +
1003 "union all " +
1004 "(select id, first_name, last_name, birth_date, employed, occupation, address_id " +
1005 "from Person " +
1006 "where id >= #{parameters.p2,jdbcType=INTEGER}) " +
1007 "order by id";
1008
1009 assertThat(selectStatement.getSelectStatement()).isEqualTo(expected);
1010 }
1011
1012 @Test
1013 void gh737() {
1014 UpdateStatementProvider updateStatement = update(person)
1015 .set(addressId).equalTo(add(addressId, value(4)))
1016 .where(id, isEqualTo(5))
1017 .build()
1018 .render(RenderingStrategies.MYBATIS3);
1019
1020 String expected = "update Person " +
1021 "set address_id = (address_id + #{parameters.p1}) " +
1022 "where id = #{parameters.p2,jdbcType=INTEGER}";
1023
1024 assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected);
1025 assertThat(updateStatement.getParameters()).containsOnly(entry("p1", 4), entry("p2", 5));
1026 }
1027 }