Browse Source

Fix mapping null enums, add tests

Travis Burtrum 8 months ago
parent
commit
9261ee216a

+ 21
- 0
common/src/main/java/com/moparisthebest/jdbc/util/ResultSetUtil.java View File

@@ -110,6 +110,11 @@ public class ResultSetUtil {
110 110
 		return c;
111 111
 	}
112 112
 
113
+	public static <T extends Enum<T>> T getEnum(final ResultSet _resultSet, final int index, final Class<T> enumType) throws SQLException {
114
+		final String name = _resultSet.getString(index);
115
+		return name == null ? null : Enum.valueOf(enumType, name);
116
+	}
117
+
113 118
 	//IFJAVA8_START
114 119
 
115 120
 	public static Instant getInstant(final ResultSet _resultSet, final int index) throws SQLException {
@@ -196,6 +201,22 @@ public class ResultSetUtil {
196 201
 		return ts == null ? null : OffsetTime.ofInstant(ts.toInstant(), _cal.getTimeZone().toZoneId());
197 202
 	}
198 203
 
204
+	public static Year getYear(final ResultSet _resultSet, final int index) throws SQLException {
205
+		// done this way instead of of(int) because usually int->string database coercion is allowed and the other isn't?
206
+		final String s = _resultSet.getString(index);
207
+		return s == null ? null : Year.parse(s);
208
+	}
209
+
210
+	public static ZoneId getZoneId(final ResultSet _resultSet, final int index) throws SQLException {
211
+		final String s = _resultSet.getString(index);
212
+		return s == null ? null : ZoneId.of(s);
213
+	}
214
+
215
+	public static ZoneOffset getZoneOffset(final ResultSet _resultSet, final int index) throws SQLException {
216
+		final String s = _resultSet.getString(index);
217
+		return s == null ? null : ZoneOffset.of(s);
218
+	}
219
+
199 220
 	//IFJAVA8_END
200 221
 
201 222
 }

+ 15
- 0
jdbcmapper/src/test/java/com/moparisthebest/jdbc/codegen/JdbcMapperTest.java View File

@@ -101,11 +101,26 @@ public class JdbcMapperTest {
101 101
 		assertEquals(new EnumPerson(FirstName.First), dao.getEnumPerson(fieldPerson1.getPersonNo()));
102 102
 	}
103 103
 
104
+	@Test
105
+	public void testEnumPersonConstructor() throws SQLException {
106
+		assertEquals(new EnumPerson(FirstName.First), dao.getEnumPersonConstructor(fieldPerson1.getPersonNo()));
107
+	}
108
+
104 109
 	@Test
105 110
 	public void testEnum() throws SQLException {
106 111
 		assertEquals(FirstName.First, dao.getFirstNameEnum(fieldPerson1.getPersonNo()));
107 112
 	}
108 113
 
114
+	@Test
115
+	public void testEnumPersonNull() throws SQLException {
116
+		assertEquals(new EnumPerson(null), dao.getEnumPersonNull());
117
+	}
118
+
119
+	@Test
120
+	public void testEnumNull() throws SQLException {
121
+		assertEquals(null, dao.getEnumNull());
122
+	}
123
+
109 124
 	//IFJAVA8_START
110 125
 
111 126
 	@Test

+ 9
- 0
jdbcmapper/src/test/java/com/moparisthebest/jdbc/codegen/PersonDAO.java View File

@@ -196,9 +196,18 @@ public interface PersonDAO extends JdbcMapper {
196 196
 	@JdbcMapper.SQL("SELECT first_name, last_name FROM person WHERE person_no = {personNo}")
197 197
 	EnumPerson getEnumPerson(long personNo) throws SQLException;
198 198
 
199
+	@JdbcMapper.SQL("SELECT first_name FROM person WHERE person_no = {personNo}")
200
+	EnumPerson getEnumPersonConstructor(long personNo) throws SQLException;
201
+
199 202
 	@JdbcMapper.SQL("SELECT first_name FROM person WHERE person_no = {personNo}")
200 203
 	FirstName getFirstNameEnum(long personNo) throws SQLException;
201 204
 
205
+	@JdbcMapper.SQL("SELECT str_val as first_name, str_val as last_name FROM val WHERE val_no = 4")
206
+	EnumPerson getEnumPersonNull() throws SQLException;
207
+
208
+	@JdbcMapper.SQL("SELECT str_val FROM val WHERE val_no = 4")
209
+	FirstName getEnumNull() throws SQLException;
210
+
202 211
 	//IFJAVA8_START
203 212
 
204 213
 	@JdbcMapper.SQL("SELECT birth_date FROM person WHERE person_no = {personNo}")

+ 21
- 21
querymapper/src/main/java/com/moparisthebest/jdbc/CompilingRowToObjectMapper.java View File

@@ -453,35 +453,35 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
453 453
 				java.append(resultSetName).append(".getInt(").append(String.valueOf(index)).append(")");
454 454
 				return;
455 455
 			case TypeMappingsFactory.TYPE_BOOLEAN:
456
-				java.append("getBooleanYN(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
456
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getBooleanYN(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
457 457
 				return;
458 458
 			case TypeMappingsFactory.TYPE_INT_OBJ:
459
-				java.append("getObjectInt(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
459
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectInt(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
460 460
 				return;
461 461
 			case TypeMappingsFactory.TYPE_LONG_OBJ:
462
-				java.append("getObjectLong(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
462
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectLong(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
463 463
 				return;
464 464
 			case TypeMappingsFactory.TYPE_FLOAT_OBJ:
465
-				java.append("getObjectFloat(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
465
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectFloat(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
466 466
 				return;
467 467
 			case TypeMappingsFactory.TYPE_DOUBLE_OBJ:
468
-				java.append("getObjectDouble(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
468
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectDouble(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
469 469
 				return;
470 470
 			case TypeMappingsFactory.TYPE_BYTE_OBJ:
471
-				java.append("getObjectByte(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
471
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectByte(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
472 472
 				return;
473 473
 			case TypeMappingsFactory.TYPE_SHORT_OBJ:
474
-				java.append("getObjectShort(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
474
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectShort(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
475 475
 				return;
476 476
 			case TypeMappingsFactory.TYPE_BOOLEAN_OBJ:
477
-				java.append("getObjectBooleanYN(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
477
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectBooleanYN(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
478 478
 				return;
479 479
 			case TypeMappingsFactory.TYPE_STRING:
480 480
 			case TypeMappingsFactory.TYPE_XMLBEAN_ENUM:
481 481
 				java.append(resultSetName).append(".getString(").append(String.valueOf(index)).append(")");
482 482
 				return;
483 483
 			case TypeMappingsFactory.TYPE_ENUM:
484
-				java.append(enumName).append(".valueOf(").append(resultSetName).append(".getString(").append(String.valueOf(index)).append("))");
484
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getEnum(").append(resultSetName).append(", ").append(String.valueOf(index)).append(", ").append(enumName).append(".class)");
485 485
 				return;
486 486
 			case TypeMappingsFactory.TYPE_BIG_DECIMAL:
487 487
 				java.append(resultSetName).append(".getBigDecimal(").append(String.valueOf(index)).append(")");
@@ -508,13 +508,13 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
508 508
 				java.append(")");
509 509
 				return;
510 510
 			case TypeMappingsFactory.TYPE_DATE:
511
-				java.append("getUtilDate(").append(resultSetName).append(", ").append(String.valueOf(index));
511
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getUtilDate(").append(resultSetName).append(", ").append(String.valueOf(index));
512 512
 				if(calendarName != null)
513 513
 					java.append(", ").append(calendarName);
514 514
 				java.append(")");
515 515
 				return;
516 516
 			case TypeMappingsFactory.TYPE_CALENDAR:
517
-				java.append("getCalendar(").append(resultSetName).append(", ").append(String.valueOf(index));
517
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getCalendar(").append(resultSetName).append(", ").append(String.valueOf(index));
518 518
 				if(calendarName != null)
519 519
 					java.append(", ").append(calendarName);
520 520
 				java.append(")");
@@ -536,56 +536,56 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
536 536
 				throw new MapperException("streaming return types are not supported by the JdbcControl; use ResultSet instead");
537 537
 			// start java.time support
538 538
 			case TypeMappingsFactory.TYPE_INSTANT:
539
-				java.append("getInstant(").append(resultSetName).append(", ").append(String.valueOf(index));
539
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getInstant(").append(resultSetName).append(", ").append(String.valueOf(index));
540 540
 				if(calendarName != null)
541 541
 					java.append(", ").append(calendarName);
542 542
 				java.append(")");
543 543
 				return;
544 544
 			case TypeMappingsFactory.TYPE_LOCALDATETIME:
545
-				java.append("getLocalDateTime(").append(resultSetName).append(", ").append(String.valueOf(index));
545
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getLocalDateTime(").append(resultSetName).append(", ").append(String.valueOf(index));
546 546
 				if(calendarName != null)
547 547
 					java.append(", ").append(calendarName);
548 548
 				java.append(")");
549 549
 				return;
550 550
 			case TypeMappingsFactory.TYPE_LOCALDATE:
551
-				java.append("getLocalDate(").append(resultSetName).append(", ").append(String.valueOf(index));
551
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getLocalDate(").append(resultSetName).append(", ").append(String.valueOf(index));
552 552
 				if(calendarName != null)
553 553
 					java.append(", ").append(calendarName);
554 554
 				java.append(")");
555 555
 				return;
556 556
 			case TypeMappingsFactory.TYPE_LOCALTIME:
557
-				java.append("getLocalTime(").append(resultSetName).append(", ").append(String.valueOf(index));
557
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getLocalTime(").append(resultSetName).append(", ").append(String.valueOf(index));
558 558
 				if(calendarName != null)
559 559
 					java.append(", ").append(calendarName);
560 560
 				java.append(")");
561 561
 				return;
562 562
 			// todo: send in ZoneId here?
563 563
 			case TypeMappingsFactory.TYPE_ZONEDDATETIME:
564
-				java.append("getZonedDateTime(").append(resultSetName).append(", ").append(String.valueOf(index));
564
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getZonedDateTime(").append(resultSetName).append(", ").append(String.valueOf(index));
565 565
 				if(calendarName != null)
566 566
 					java.append(", ").append(calendarName);
567 567
 				java.append(")");
568 568
 				return;
569 569
 			case TypeMappingsFactory.TYPE_OFFSETDATETIME:
570
-				java.append("getOffsetDateTime(").append(resultSetName).append(", ").append(String.valueOf(index));
570
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getOffsetDateTime(").append(resultSetName).append(", ").append(String.valueOf(index));
571 571
 				if(calendarName != null)
572 572
 					java.append(", ").append(calendarName);
573 573
 				java.append(")");
574 574
 				return;
575 575
 			case TypeMappingsFactory.TYPE_OFFSETTIME:
576
-				java.append("getOffsetTime(").append(resultSetName).append(", ").append(String.valueOf(index));
576
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getOffsetTime(").append(resultSetName).append(", ").append(String.valueOf(index));
577 577
 				if(calendarName != null)
578 578
 					java.append(", ").append(calendarName);
579 579
 				java.append(")");
580 580
 				return;
581 581
 			case TypeMappingsFactory.TYPE_YEAR:
582
-				java.append("java.time.Year.parse(").append(resultSetName).append(".getString(").append(String.valueOf(index)).append("))");
582
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getYear(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
583 583
 				return;
584 584
 			case TypeMappingsFactory.TYPE_ZONEID:
585
-				java.append("java.time.ZoneId.of(").append(resultSetName).append(".getString(").append(String.valueOf(index)).append("))");
585
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getZoneId(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
586 586
 				return;
587 587
 			case TypeMappingsFactory.TYPE_ZONEOFFSET:
588
-				java.append("java.time.ZoneOffset.of(").append(resultSetName).append(".getString(").append(String.valueOf(index)).append("))");
588
+				java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getZoneOffset(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
589 589
 				return;
590 590
 			// end java.time support
591 591
 			case TypeMappingsFactory.TYPE_STRUCT:

+ 4
- 5
querymapper/src/main/java/com/moparisthebest/jdbc/RowToObjectMapper.java View File

@@ -654,7 +654,7 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
654 654
 					return _resultSet.getString(index);
655 655
 				case TypeMappingsFactory.TYPE_ENUM:
656 656
 					@SuppressWarnings("unchecked")
657
-					final Enum ret = Enum.valueOf((Class<? extends Enum>)resultTypeClass, _resultSet.getString(index));
657
+					final Enum ret = ResultSetUtil.getEnum(_resultSet, index, (Class<? extends Enum>) resultTypeClass);
658 658
 					return ret;
659 659
 				case TypeMappingsFactory.TYPE_BIG_DECIMAL:
660 660
 					return _resultSet.getBigDecimal(index);
@@ -728,12 +728,11 @@ public class RowToObjectMapper<K, T> extends AbstractRowMapper<K, T> {
728 728
 				case TypeMappingsFactory.TYPE_OFFSETTIME:
729 729
 					return ResultSetUtil.getOffsetTime(_resultSet, index, _cal);
730 730
 				case TypeMappingsFactory.TYPE_YEAR:
731
-					// done this way instead of of(int) because usually int->string database coercion is allowed and the other isn't?
732
-					return Year.parse(_resultSet.getString(index));
731
+					return ResultSetUtil.getYear(_resultSet, index);
733 732
 				case TypeMappingsFactory.TYPE_ZONEID:
734
-					return ZoneId.of(_resultSet.getString(index));
733
+					return ResultSetUtil.getZoneId(_resultSet, index);
735 734
 				case TypeMappingsFactory.TYPE_ZONEOFFSET:
736
-					return ZoneOffset.of(_resultSet.getString(index));
735
+					return ResultSetUtil.getZoneOffset(_resultSet, index);
737 736
 				// end java.time support
738 737
 				//IFJAVA8_END
739 738
 				case TypeMappingsFactory.TYPE_STRUCT:

+ 23
- 1
querymapper/src/test/java/com/moparisthebest/jdbc/QueryMapperTest.java View File

@@ -36,6 +36,8 @@ public class QueryMapperTest {
36 36
 	public static final Person fieldPerson2 = new FieldPerson(5, new Date(0), "Second", "Person");
37 37
 	public static final Person fieldPerson3 = new FieldPerson(6, new Date(0), "Third", "Person");
38 38
 
39
+	public static final Person fieldPerson1NullName = new FieldPerson(1, new Date(0), null, null);
40
+
39 41
 	public static final Person[] people = new Person[]{fieldPerson1, fieldPerson2, fieldPerson3};
40 42
 	public static final Boss[] bosses = new Boss[]{fieldBoss1, fieldBoss2, fieldBoss3};
41 43
 
@@ -43,6 +45,7 @@ public class QueryMapperTest {
43 45
 			new Val(1, 1969, "1969"),
44 46
 			new Val(2, 0, "America/New_York"),
45 47
 			new Val(3, -5, "-5"),
48
+			new Val(4, 4, null),
46 49
 	};
47 50
 
48 51
 	public static final Person setPerson1 = new SetPerson(fieldPerson1);
@@ -91,7 +94,7 @@ public class QueryMapperTest {
91 94
 				qm.executeUpdate("CREATE TABLE boss (person_no NUMERIC, department VARCHAR(40))");
92 95
 				qm.executeUpdate("CREATE TABLE val (val_no NUMERIC, num_val NUMERIC, str_val VARCHAR(40))");
93 96
 				for (final Person person : people)
94
-					qm.executeUpdate("INSERT INTO person (person_no, birth_date, last_name, first_name) VALUES (?, ?, ?, ?)", person.getPersonNo(), person.getBirthDate(), person.getLastName(), person.getFirstName());
97
+					insertPerson(qm, person);
95 98
 				for (final Boss boss : bosses) {
96 99
 					qm.executeUpdate("INSERT INTO person (person_no, birth_date, last_name, first_name) VALUES (?, ?, ?, ?)", boss.getPersonNo(), boss.getBirthDate(), boss.getLastName(), boss.getFirstName() == null ? boss.getFirst_name() : boss.getFirstName());
97 100
 					qm.executeUpdate("INSERT INTO boss (person_no, department) VALUES (?, ?)", boss.getPersonNo(), boss.getDepartment());
@@ -108,6 +111,10 @@ public class QueryMapperTest {
108 111
 		}
109 112
 	}
110 113
 
114
+	public static void insertPerson(final QueryMapper qm, final Person person) throws SQLException {
115
+		qm.executeUpdate("INSERT INTO person (person_no, birth_date, last_name, first_name) VALUES (?, ?, ?, ?)", person.getPersonNo(), person.getBirthDate(), person.getLastName(), person.getFirstName());
116
+	}
117
+
111 118
 	public static Connection getConnection() throws SQLException {
112 119
 		return DriverManager.getConnection("jdbc:derby:memory:derbyDB;create=true");
113 120
 	}
@@ -450,11 +457,26 @@ public class QueryMapperTest {
450 457
 		assertEquals(new EnumPerson(FirstName.First), qm.toObject("SELECT first_name, last_name FROM person WHERE person_no = ?", EnumPerson.class, fieldPerson1.getPersonNo()));
451 458
 	}
452 459
 
460
+	@Test
461
+	public void testEnumPersonConstructor() throws SQLException {
462
+		assertEquals(new EnumPerson(FirstName.First), qm.toObject("SELECT first_name FROM person WHERE person_no = ?", EnumPerson.class, fieldPerson1.getPersonNo()));
463
+	}
464
+
453 465
 	@Test
454 466
 	public void testEnum() throws SQLException {
455 467
 		assertEquals(FirstName.First, qm.toObject("SELECT first_name FROM person WHERE person_no = ?", FirstName.class, fieldPerson1.getPersonNo()));
456 468
 	}
457 469
 
470
+	@Test
471
+	public void testEnumPersonNull() throws SQLException {
472
+		assertEquals(new EnumPerson(null), qm.toObject("SELECT str_val as first_name, str_val as last_name FROM val WHERE val_no = 4", EnumPerson.class));
473
+	}
474
+
475
+	@Test
476
+	public void testEnumNull() throws SQLException {
477
+		assertEquals(null, qm.toObject("SELECT str_val FROM val WHERE val_no = 4", FirstName.class));
478
+	}
479
+
458 480
 	//IFJAVA8_START
459 481
 
460 482
 	@Test