Fix mapping null enums, add tests

This commit is contained in:
Travis Burtrum 2018-01-12 16:46:22 -05:00
parent c6bde5233d
commit 9261ee216a
6 changed files with 93 additions and 27 deletions

View File

@ -110,6 +110,11 @@ public class ResultSetUtil {
return c; return c;
} }
public static <T extends Enum<T>> T getEnum(final ResultSet _resultSet, final int index, final Class<T> enumType) throws SQLException {
final String name = _resultSet.getString(index);
return name == null ? null : Enum.valueOf(enumType, name);
}
//IFJAVA8_START //IFJAVA8_START
public static Instant getInstant(final ResultSet _resultSet, final int index) throws SQLException { public static Instant getInstant(final ResultSet _resultSet, final int index) throws SQLException {
@ -196,6 +201,22 @@ public class ResultSetUtil {
return ts == null ? null : OffsetTime.ofInstant(ts.toInstant(), _cal.getTimeZone().toZoneId()); return ts == null ? null : OffsetTime.ofInstant(ts.toInstant(), _cal.getTimeZone().toZoneId());
} }
public static Year getYear(final ResultSet _resultSet, final int index) throws SQLException {
// done this way instead of of(int) because usually int->string database coercion is allowed and the other isn't?
final String s = _resultSet.getString(index);
return s == null ? null : Year.parse(s);
}
public static ZoneId getZoneId(final ResultSet _resultSet, final int index) throws SQLException {
final String s = _resultSet.getString(index);
return s == null ? null : ZoneId.of(s);
}
public static ZoneOffset getZoneOffset(final ResultSet _resultSet, final int index) throws SQLException {
final String s = _resultSet.getString(index);
return s == null ? null : ZoneOffset.of(s);
}
//IFJAVA8_END //IFJAVA8_END
} }

View File

@ -101,11 +101,26 @@ public class JdbcMapperTest {
assertEquals(new EnumPerson(FirstName.First), dao.getEnumPerson(fieldPerson1.getPersonNo())); assertEquals(new EnumPerson(FirstName.First), dao.getEnumPerson(fieldPerson1.getPersonNo()));
} }
@Test
public void testEnumPersonConstructor() throws SQLException {
assertEquals(new EnumPerson(FirstName.First), dao.getEnumPersonConstructor(fieldPerson1.getPersonNo()));
}
@Test @Test
public void testEnum() throws SQLException { public void testEnum() throws SQLException {
assertEquals(FirstName.First, dao.getFirstNameEnum(fieldPerson1.getPersonNo())); assertEquals(FirstName.First, dao.getFirstNameEnum(fieldPerson1.getPersonNo()));
} }
@Test
public void testEnumPersonNull() throws SQLException {
assertEquals(new EnumPerson(null), dao.getEnumPersonNull());
}
@Test
public void testEnumNull() throws SQLException {
assertEquals(null, dao.getEnumNull());
}
//IFJAVA8_START //IFJAVA8_START
@Test @Test

View File

@ -196,9 +196,18 @@ public interface PersonDAO extends JdbcMapper {
@JdbcMapper.SQL("SELECT first_name, last_name FROM person WHERE person_no = {personNo}") @JdbcMapper.SQL("SELECT first_name, last_name FROM person WHERE person_no = {personNo}")
EnumPerson getEnumPerson(long personNo) throws SQLException; EnumPerson getEnumPerson(long personNo) throws SQLException;
@JdbcMapper.SQL("SELECT first_name FROM person WHERE person_no = {personNo}")
EnumPerson getEnumPersonConstructor(long personNo) throws SQLException;
@JdbcMapper.SQL("SELECT first_name FROM person WHERE person_no = {personNo}") @JdbcMapper.SQL("SELECT first_name FROM person WHERE person_no = {personNo}")
FirstName getFirstNameEnum(long personNo) throws SQLException; FirstName getFirstNameEnum(long personNo) throws SQLException;
@JdbcMapper.SQL("SELECT str_val as first_name, str_val as last_name FROM val WHERE val_no = 4")
EnumPerson getEnumPersonNull() throws SQLException;
@JdbcMapper.SQL("SELECT str_val FROM val WHERE val_no = 4")
FirstName getEnumNull() throws SQLException;
//IFJAVA8_START //IFJAVA8_START
@JdbcMapper.SQL("SELECT birth_date FROM person WHERE person_no = {personNo}") @JdbcMapper.SQL("SELECT birth_date FROM person WHERE person_no = {personNo}")

View File

@ -453,35 +453,35 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
java.append(resultSetName).append(".getInt(").append(String.valueOf(index)).append(")"); java.append(resultSetName).append(".getInt(").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_BOOLEAN: case TypeMappingsFactory.TYPE_BOOLEAN:
java.append("getBooleanYN(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getBooleanYN(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_INT_OBJ: case TypeMappingsFactory.TYPE_INT_OBJ:
java.append("getObjectInt(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectInt(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_LONG_OBJ: case TypeMappingsFactory.TYPE_LONG_OBJ:
java.append("getObjectLong(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectLong(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_FLOAT_OBJ: case TypeMappingsFactory.TYPE_FLOAT_OBJ:
java.append("getObjectFloat(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectFloat(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_DOUBLE_OBJ: case TypeMappingsFactory.TYPE_DOUBLE_OBJ:
java.append("getObjectDouble(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectDouble(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_BYTE_OBJ: case TypeMappingsFactory.TYPE_BYTE_OBJ:
java.append("getObjectByte(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectByte(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_SHORT_OBJ: case TypeMappingsFactory.TYPE_SHORT_OBJ:
java.append("getObjectShort(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectShort(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_BOOLEAN_OBJ: case TypeMappingsFactory.TYPE_BOOLEAN_OBJ:
java.append("getObjectBooleanYN(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getObjectBooleanYN(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_STRING: case TypeMappingsFactory.TYPE_STRING:
case TypeMappingsFactory.TYPE_XMLBEAN_ENUM: case TypeMappingsFactory.TYPE_XMLBEAN_ENUM:
java.append(resultSetName).append(".getString(").append(String.valueOf(index)).append(")"); java.append(resultSetName).append(".getString(").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_ENUM: case TypeMappingsFactory.TYPE_ENUM:
java.append(enumName).append(".valueOf(").append(resultSetName).append(".getString(").append(String.valueOf(index)).append("))"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getEnum(").append(resultSetName).append(", ").append(String.valueOf(index)).append(", ").append(enumName).append(".class)");
return; return;
case TypeMappingsFactory.TYPE_BIG_DECIMAL: case TypeMappingsFactory.TYPE_BIG_DECIMAL:
java.append(resultSetName).append(".getBigDecimal(").append(String.valueOf(index)).append(")"); java.append(resultSetName).append(".getBigDecimal(").append(String.valueOf(index)).append(")");
@ -508,13 +508,13 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
java.append(")"); java.append(")");
return; return;
case TypeMappingsFactory.TYPE_DATE: case TypeMappingsFactory.TYPE_DATE:
java.append("getUtilDate(").append(resultSetName).append(", ").append(String.valueOf(index)); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getUtilDate(").append(resultSetName).append(", ").append(String.valueOf(index));
if(calendarName != null) if(calendarName != null)
java.append(", ").append(calendarName); java.append(", ").append(calendarName);
java.append(")"); java.append(")");
return; return;
case TypeMappingsFactory.TYPE_CALENDAR: case TypeMappingsFactory.TYPE_CALENDAR:
java.append("getCalendar(").append(resultSetName).append(", ").append(String.valueOf(index)); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getCalendar(").append(resultSetName).append(", ").append(String.valueOf(index));
if(calendarName != null) if(calendarName != null)
java.append(", ").append(calendarName); java.append(", ").append(calendarName);
java.append(")"); java.append(")");
@ -536,56 +536,56 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
throw new MapperException("streaming return types are not supported by the JdbcControl; use ResultSet instead"); throw new MapperException("streaming return types are not supported by the JdbcControl; use ResultSet instead");
// start java.time support // start java.time support
case TypeMappingsFactory.TYPE_INSTANT: case TypeMappingsFactory.TYPE_INSTANT:
java.append("getInstant(").append(resultSetName).append(", ").append(String.valueOf(index)); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getInstant(").append(resultSetName).append(", ").append(String.valueOf(index));
if(calendarName != null) if(calendarName != null)
java.append(", ").append(calendarName); java.append(", ").append(calendarName);
java.append(")"); java.append(")");
return; return;
case TypeMappingsFactory.TYPE_LOCALDATETIME: case TypeMappingsFactory.TYPE_LOCALDATETIME:
java.append("getLocalDateTime(").append(resultSetName).append(", ").append(String.valueOf(index)); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getLocalDateTime(").append(resultSetName).append(", ").append(String.valueOf(index));
if(calendarName != null) if(calendarName != null)
java.append(", ").append(calendarName); java.append(", ").append(calendarName);
java.append(")"); java.append(")");
return; return;
case TypeMappingsFactory.TYPE_LOCALDATE: case TypeMappingsFactory.TYPE_LOCALDATE:
java.append("getLocalDate(").append(resultSetName).append(", ").append(String.valueOf(index)); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getLocalDate(").append(resultSetName).append(", ").append(String.valueOf(index));
if(calendarName != null) if(calendarName != null)
java.append(", ").append(calendarName); java.append(", ").append(calendarName);
java.append(")"); java.append(")");
return; return;
case TypeMappingsFactory.TYPE_LOCALTIME: case TypeMappingsFactory.TYPE_LOCALTIME:
java.append("getLocalTime(").append(resultSetName).append(", ").append(String.valueOf(index)); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getLocalTime(").append(resultSetName).append(", ").append(String.valueOf(index));
if(calendarName != null) if(calendarName != null)
java.append(", ").append(calendarName); java.append(", ").append(calendarName);
java.append(")"); java.append(")");
return; return;
// todo: send in ZoneId here? // todo: send in ZoneId here?
case TypeMappingsFactory.TYPE_ZONEDDATETIME: case TypeMappingsFactory.TYPE_ZONEDDATETIME:
java.append("getZonedDateTime(").append(resultSetName).append(", ").append(String.valueOf(index)); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getZonedDateTime(").append(resultSetName).append(", ").append(String.valueOf(index));
if(calendarName != null) if(calendarName != null)
java.append(", ").append(calendarName); java.append(", ").append(calendarName);
java.append(")"); java.append(")");
return; return;
case TypeMappingsFactory.TYPE_OFFSETDATETIME: case TypeMappingsFactory.TYPE_OFFSETDATETIME:
java.append("getOffsetDateTime(").append(resultSetName).append(", ").append(String.valueOf(index)); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getOffsetDateTime(").append(resultSetName).append(", ").append(String.valueOf(index));
if(calendarName != null) if(calendarName != null)
java.append(", ").append(calendarName); java.append(", ").append(calendarName);
java.append(")"); java.append(")");
return; return;
case TypeMappingsFactory.TYPE_OFFSETTIME: case TypeMappingsFactory.TYPE_OFFSETTIME:
java.append("getOffsetTime(").append(resultSetName).append(", ").append(String.valueOf(index)); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getOffsetTime(").append(resultSetName).append(", ").append(String.valueOf(index));
if(calendarName != null) if(calendarName != null)
java.append(", ").append(calendarName); java.append(", ").append(calendarName);
java.append(")"); java.append(")");
return; return;
case TypeMappingsFactory.TYPE_YEAR: case TypeMappingsFactory.TYPE_YEAR:
java.append("java.time.Year.parse(").append(resultSetName).append(".getString(").append(String.valueOf(index)).append("))"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getYear(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_ZONEID: case TypeMappingsFactory.TYPE_ZONEID:
java.append("java.time.ZoneId.of(").append(resultSetName).append(".getString(").append(String.valueOf(index)).append("))"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getZoneId(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
case TypeMappingsFactory.TYPE_ZONEOFFSET: case TypeMappingsFactory.TYPE_ZONEOFFSET:
java.append("java.time.ZoneOffset.of(").append(resultSetName).append(".getString(").append(String.valueOf(index)).append("))"); java.append("com.moparisthebest.jdbc.util.ResultSetUtil.getZoneOffset(").append(resultSetName).append(", ").append(String.valueOf(index)).append(")");
return; return;
// end java.time support // end java.time support
case TypeMappingsFactory.TYPE_STRUCT: case TypeMappingsFactory.TYPE_STRUCT:

View File

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

View File

@ -36,6 +36,8 @@ public class QueryMapperTest {
public static final Person fieldPerson2 = new FieldPerson(5, new Date(0), "Second", "Person"); public static final Person fieldPerson2 = new FieldPerson(5, new Date(0), "Second", "Person");
public static final Person fieldPerson3 = new FieldPerson(6, new Date(0), "Third", "Person"); public static final Person fieldPerson3 = new FieldPerson(6, new Date(0), "Third", "Person");
public static final Person fieldPerson1NullName = new FieldPerson(1, new Date(0), null, null);
public static final Person[] people = new Person[]{fieldPerson1, fieldPerson2, fieldPerson3}; public static final Person[] people = new Person[]{fieldPerson1, fieldPerson2, fieldPerson3};
public static final Boss[] bosses = new Boss[]{fieldBoss1, fieldBoss2, fieldBoss3}; public static final Boss[] bosses = new Boss[]{fieldBoss1, fieldBoss2, fieldBoss3};
@ -43,6 +45,7 @@ public class QueryMapperTest {
new Val(1, 1969, "1969"), new Val(1, 1969, "1969"),
new Val(2, 0, "America/New_York"), new Val(2, 0, "America/New_York"),
new Val(3, -5, "-5"), new Val(3, -5, "-5"),
new Val(4, 4, null),
}; };
public static final Person setPerson1 = new SetPerson(fieldPerson1); public static final Person setPerson1 = new SetPerson(fieldPerson1);
@ -91,7 +94,7 @@ public class QueryMapperTest {
qm.executeUpdate("CREATE TABLE boss (person_no NUMERIC, department VARCHAR(40))"); qm.executeUpdate("CREATE TABLE boss (person_no NUMERIC, department VARCHAR(40))");
qm.executeUpdate("CREATE TABLE val (val_no NUMERIC, num_val NUMERIC, str_val VARCHAR(40))"); qm.executeUpdate("CREATE TABLE val (val_no NUMERIC, num_val NUMERIC, str_val VARCHAR(40))");
for (final Person person : people) for (final Person person : people)
qm.executeUpdate("INSERT INTO person (person_no, birth_date, last_name, first_name) VALUES (?, ?, ?, ?)", person.getPersonNo(), person.getBirthDate(), person.getLastName(), person.getFirstName()); insertPerson(qm, person);
for (final Boss boss : bosses) { for (final Boss boss : bosses) {
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()); 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());
qm.executeUpdate("INSERT INTO boss (person_no, department) VALUES (?, ?)", boss.getPersonNo(), boss.getDepartment()); qm.executeUpdate("INSERT INTO boss (person_no, department) VALUES (?, ?)", boss.getPersonNo(), boss.getDepartment());
@ -108,6 +111,10 @@ public class QueryMapperTest {
} }
} }
public static void insertPerson(final QueryMapper qm, final Person person) throws SQLException {
qm.executeUpdate("INSERT INTO person (person_no, birth_date, last_name, first_name) VALUES (?, ?, ?, ?)", person.getPersonNo(), person.getBirthDate(), person.getLastName(), person.getFirstName());
}
public static Connection getConnection() throws SQLException { public static Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:derby:memory:derbyDB;create=true"); return DriverManager.getConnection("jdbc:derby:memory:derbyDB;create=true");
} }
@ -450,11 +457,26 @@ public class QueryMapperTest {
assertEquals(new EnumPerson(FirstName.First), qm.toObject("SELECT first_name, last_name FROM person WHERE person_no = ?", EnumPerson.class, fieldPerson1.getPersonNo())); assertEquals(new EnumPerson(FirstName.First), qm.toObject("SELECT first_name, last_name FROM person WHERE person_no = ?", EnumPerson.class, fieldPerson1.getPersonNo()));
} }
@Test
public void testEnumPersonConstructor() throws SQLException {
assertEquals(new EnumPerson(FirstName.First), qm.toObject("SELECT first_name FROM person WHERE person_no = ?", EnumPerson.class, fieldPerson1.getPersonNo()));
}
@Test @Test
public void testEnum() throws SQLException { public void testEnum() throws SQLException {
assertEquals(FirstName.First, qm.toObject("SELECT first_name FROM person WHERE person_no = ?", FirstName.class, fieldPerson1.getPersonNo())); assertEquals(FirstName.First, qm.toObject("SELECT first_name FROM person WHERE person_no = ?", FirstName.class, fieldPerson1.getPersonNo()));
} }
@Test
public void testEnumPersonNull() throws SQLException {
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));
}
@Test
public void testEnumNull() throws SQLException {
assertEquals(null, qm.toObject("SELECT str_val FROM val WHERE val_no = 4", FirstName.class));
}
//IFJAVA8_START //IFJAVA8_START
@Test @Test