Add ResultSetIterable support to querymapper

This commit is contained in:
Travis Burtrum 2017-06-08 23:02:12 -04:00
parent d80a9325d7
commit d74c272e73
13 changed files with 419 additions and 13 deletions

View File

@ -0,0 +1,153 @@
package com.moparisthebest.jdbc.util;
import java.io.Closeable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Iterator;
import java.util.NoSuchElementException;
import static com.moparisthebest.jdbc.TryClose.tryClose;
/**
* Iterable/Iterator interface over a ResultSet
* <p>
* This has some special semantics the caller must be aware of though:
* <p>
* 1. It has to be closed in a finally just like a ResultSet so it can close it's underlying ResultSet
* 2. Call to .iterator() just returns this, meaning you can only loop over it once, if you need to loop multiple times get a List or something
* 3. This guarantees that the ResultSet/Calendar you send into this class with the ResultSetToObject will be the only
* instances sent into the ResultSetToObject.toObject() method, so if you do fancy initialization of some sort you can
* do it in the constructor based on those instances, or once on the first call to .toObject() and cache it forever.
* Or it can be entirely stateless and re-used across multiple ResultSets, your choice.
* 4. If you set a PreparedStatement to close, you can only set it once, and it will close it when you call .close() on this
*/
public class ResultSetIterable<T> implements Iterable<T>, Iterator<T>, Closeable {
public static final ResultSetIterable EMPTY_RESULT_SET_ITERABLE = new EmptyResultSetIterable();
@SuppressWarnings("unchecked")
public static <T> ResultSetIterable<T> emptyResultSetIterable() {
return (ResultSetIterable<T>) EMPTY_RESULT_SET_ITERABLE;
}
public static <T> ResultSetIterable<T> getResultSetIterable(final ResultSet rs, final ResultSetToObject<T> rsto) {
return getResultSetIterable(rs, rsto, null);
}
/**
* This is a convenience method meant to be called like this, where rs is a ResultSet
* <p>
* ResultSetIterable<T> rsi = ResultSetIterable.getResultSetIterable(rs, rs.next() ? complicatedBuildResultSetToObject(rs) : null, cal);
* <p>
* This way you can avoid building or sending in a ResultSetToObject all together if there are no rows, therefore if rsto
* sent into this is null, it returns an EMPTY_RESULT_SET_ITERABLE
* <p>
* This assumes rs.next() was called once before sent into this function
*/
@SuppressWarnings("unchecked")
public static <T> ResultSetIterable<T> getResultSetIterable(final ResultSet rs, final ResultSetToObject<T> rsto, final Calendar cal) {
if (rsto == null)
return (ResultSetIterable<T>) EMPTY_RESULT_SET_ITERABLE;
final ResultSetIterable<T> ret = new ResultSetIterable<T>(rs, rsto, cal);
ret.calledNext = true;
return ret;
}
private final ResultSet rs;
private final Calendar cal;
private final ResultSetToObject<T> rsto;
private boolean calledNext = false;
private PreparedStatement ps = null;
protected ResultSetIterable() {
this.rs = null;
this.cal = null;
this.rsto = null;
}
public ResultSetIterable(final ResultSet rs, final ResultSetToObject<T> rsto) {
this(rs, rsto, null);
}
public ResultSetIterable(final ResultSet rs, final ResultSetToObject<T> rsto, final Calendar cal) {
if (rs == null || rsto == null)
throw new NullPointerException("rs and rsto must be non-null");
this.rs = rs;
this.cal = cal;
this.rsto = rsto;
}
public ResultSetIterable<T> setPreparedStatementToClose(final PreparedStatement ps) {
if (this.ps != null)
throw new IllegalStateException("can only set PreparedStatement to close once");
this.ps = ps;
return this;
}
@Override
public Iterator<T> iterator() {
return this;
}
@Override
public boolean hasNext() {
if (calledNext)
return true;
try {
calledNext = true;
return rs.next();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public T next() {
try {
if (!calledNext)
rs.next();
else
calledNext = false;
return rsto.toObject(rs, cal);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove unsupported");
}
@Override
public void close() {
tryClose(rs);
tryClose(ps);
}
private static class EmptyResultSetIterable extends ResultSetIterable {
@Override
public ResultSetIterable setPreparedStatementToClose(final PreparedStatement ps) {
tryClose(ps);
return this;
}
@Override
public boolean hasNext() {
return false;
}
@Override
public Object next() {
throw new NoSuchElementException("empty ResultSet");
}
@Override
public void close() {
// do nothing
}
}
}

View File

@ -0,0 +1,12 @@
package com.moparisthebest.jdbc.util;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
/**
* Created by mopar on 6/9/17.
*/
public interface ResultSetToObject<T> {
T toObject(final ResultSet rs, final Calendar cal) throws SQLException;
}

View File

@ -22,7 +22,7 @@ function finishFile(){
result="$(prepareFile "src/main/java/com/moparisthebest/jdbc/ResultSetMapper.java")"
# single object types
cat src/main/java/com/moparisthebest/jdbc/ResultSetMapper.java | grep public | egrep '(toObject|toSingleMap)\(' | grep ', Calendar cal)' | while read method
cat src/main/java/com/moparisthebest/jdbc/ResultSetMapper.java | grep public | egrep '(toObject|toSingleMap|toResultSetIterable|toResultSetIterableMap)\(' | grep ', Calendar cal)' | while read method
do
#echo "method: $method"
method_name=$(echo $method | egrep -o '[^ ]+\(')
@ -73,6 +73,12 @@ do
return cm.$method_name$(echo $method | sed -e 's/^.*(//' -e 's/final //g' -e 's/, [^ ]* /, /g' -e 's/ResultSet rs/bindExecute(ps, bindObjects)/' -e 's/) {/);/')
}
EOF
# handle this specially in QueryMapper because we need it to hold open PreparedStatement until the ResultSetIterable is closed
if [ "$method_name" != 'toResultSetIterable(' -a "$method_name" != 'toResultSetIterableMap(' ]; then
cat >> "$query" <<EOF
$(echo $method | sed -e 's/ResultSet rs/String sql/' -e 's/) {/, final Object... bindObjects) throws SQLException {/')
PreparedStatement ps = null;
try {
@ -85,6 +91,8 @@ do
EOF
fi # end special case toResultSetIterable
# CachingQueryMapper.java
cat >> "$caching_query" <<EOF
@Override

View File

@ -19,6 +19,8 @@
package com.moparisthebest.jdbc;
import com.moparisthebest.jdbc.util.ResultSetToObject;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
@ -33,7 +35,7 @@ import java.util.Calendar;
* RowMapperFactory.
*
*/
public abstract class AbstractRowMapper<K, T> implements RowMapper<K,T> {
public abstract class AbstractRowMapper<K, T> implements RowMapper<K,T>, ResultSetToObject<T> {
/** ResultSet to map. */
protected final ResultSet _resultSet;
@ -110,4 +112,14 @@ public abstract class AbstractRowMapper<K, T> implements RowMapper<K,T> {
}
return this.keys = keys;
}
@Override
public T toObject(final ResultSet rs, final Calendar cal) throws SQLException {
return this.mapRowToReturnType();
}
@Override
public ResultSetToObject<T> getResultSetToObject() {
return this;
}
}

View File

@ -1,5 +1,7 @@
package com.moparisthebest.jdbc;
import com.moparisthebest.jdbc.util.ResultSetIterable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -137,6 +139,16 @@ public class CachingQueryMapper extends QueryMapper {
return super.toObject(getPreparedStatement(sql), componentType, bindObjects);
}
@Override
public <T> ResultSetIterable<T> toResultSetIterable(String sql, Class<T> componentType, final Object... bindObjects) throws SQLException {
return super.toResultSetIterable(getPreparedStatement(sql), componentType, bindObjects);
}
@Override
public <T extends Map<String, V>, V> ResultSetIterable<Map<String, V>> toResultSetIterableMap(String sql, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toResultSetIterableMap(getPreparedStatement(sql), componentType, mapValType, bindObjects);
}
@Override
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(String sql, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toSingleMap(getPreparedStatement(sql), componentType, mapValType, bindObjects);

View File

@ -1,13 +1,16 @@
package com.moparisthebest.jdbc;
import com.moparisthebest.jdbc.util.ResultSetToObject;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
public class CleaningRowToObjectMapper<K, T> implements RowMapper<K, T> {
public class CleaningRowToObjectMapper<K, T> implements RowMapper<K, T>, ResultSetToObject<T> {
private final Cleaner<T> cleaner;
private final RowMapper<K,T> delegate;
private ResultSetToObject<T> delegateRsto = null;
public CleaningRowToObjectMapper(Cleaner<T> cleaner, ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
this(cleaner, new RowToObjectMapper<K, T>(resultSet, returnTypeClass, cal, mapValType, mapKeyType));
@ -27,4 +30,16 @@ public class CleaningRowToObjectMapper<K, T> implements RowMapper<K, T> {
public K getMapKey() throws SQLException {
return delegate.getMapKey();
}
@Override
public T toObject(final ResultSet rs, final Calendar cal) throws SQLException {
return cleaner.clean(this.delegateRsto.toObject(rs, cal));
}
@Override
public ResultSetToObject<T> getResultSetToObject() {
if(this.delegateRsto == null)
this.delegateRsto = delegate.getResultSetToObject();
return this;
}
}

View File

@ -2,7 +2,6 @@ package com.moparisthebest.jdbc;
import com.moparisthebest.classgen.Compiler;
import javax.lang.model.type.TypeMirror;
import java.io.IOException;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
@ -83,6 +82,16 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
return resultSetToObject.getFirstColumn(_resultSet, _cal);
}
@Override
public T toObject(final ResultSet rs, final Calendar cal) throws SQLException {
return resultSetToObject.toObject(rs, cal);
}
@Override
public com.moparisthebest.jdbc.util.ResultSetToObject<T> getResultSetToObject() {
return resultSetToObject;
}
@Override
protected String[] getKeysFromResultSet() throws SQLException {
if (keys == null)
@ -95,7 +104,7 @@ public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
throw new MapperException("not supported here");
}
public interface ResultSetToObject<K, T> {
public interface ResultSetToObject<K, T> extends com.moparisthebest.jdbc.util.ResultSetToObject<T> {
K getFirstColumn(final ResultSet rs, final Calendar cal) throws SQLException;
T toObject(final ResultSet rs, final Calendar cal) throws SQLException;
}

View File

@ -1,5 +1,7 @@
package com.moparisthebest.jdbc;
import com.moparisthebest.jdbc.util.ResultSetIterable;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
@ -240,6 +242,26 @@ public class ListQueryMapper extends QueryMapper {
return delegate.toObject(prepareSql(sql, bindObjects), componentType, bindObjects);
}
@Override
public <T> ResultSetIterable<T> toResultSetIterable(PreparedStatement ps, Class<T> componentType, final Object... bindObjects) throws SQLException {
return delegate.toResultSetIterable(ps, componentType, bindObjects);
}
@Override
public <T> ResultSetIterable<T> toResultSetIterable(String sql, Class<T> componentType, final Object... bindObjects) throws SQLException {
return delegate.toResultSetIterable(prepareSql(sql, bindObjects), componentType, bindObjects);
}
@Override
public <T extends Map<String, V>, V> ResultSetIterable<Map<String, V>> toResultSetIterableMap(PreparedStatement ps, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return delegate.toResultSetIterableMap(ps, componentType, mapValType, bindObjects);
}
@Override
public <T extends Map<String, V>, V> ResultSetIterable<Map<String, V>> toResultSetIterableMap(String sql, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return delegate.toResultSetIterableMap(prepareSql(sql, bindObjects), componentType, mapValType, bindObjects);
}
@Override
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(PreparedStatement ps, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return delegate.toSingleMap(ps, componentType, mapValType, bindObjects);

View File

@ -1,5 +1,7 @@
package com.moparisthebest.jdbc;
import com.moparisthebest.jdbc.util.ResultSetIterable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -257,6 +259,46 @@ public class NullQueryMapper extends QueryMapper {
return null;
}
@Override
public <T> ResultSetIterable<T> toResultSetIterable(PreparedStatement query, Class<T> componentType, final Object... bindObjects) {
try {
return delegate.toResultSetIterable(query, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T> ResultSetIterable<T> toResultSetIterable(String query, Class<T> componentType, final Object... bindObjects) {
try {
return delegate.toResultSetIterable(query, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> ResultSetIterable<Map<String, V>> toResultSetIterableMap(PreparedStatement query, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toResultSetIterableMap(query, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> ResultSetIterable<Map<String, V>> toResultSetIterableMap(String query, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toResultSetIterableMap(query, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(PreparedStatement query, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) {
try {

View File

@ -1,5 +1,7 @@
package com.moparisthebest.jdbc;
import com.moparisthebest.jdbc.util.ResultSetIterable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
@ -338,6 +340,48 @@ public class QueryMapper implements Closeable {
}
}
// these are handled specially and not generated because we need it to hold open PreparedStatement until the ResultSetIterable is closed
public <T> ResultSetIterable<T> toResultSetIterable(String sql, Class<T> componentType, final Object... bindObjects) throws SQLException {
boolean error = true;
PreparedStatement ps = null;
ResultSet rs = null;
ResultSetIterable<T> ret = null;
try {
ps = conn.prepareStatement(sql);
rs = this.toResultSet(ps, bindObjects);
ret = cm.toResultSetIterable(rs, componentType).setPreparedStatementToClose(ps);
error = false;
return ret;
} finally {
if (error) {
tryClose(ret);
tryClose(rs);
tryClose(ps);
}
}
}
public <T extends Map<String, V>, V> ResultSetIterable<Map<String, V>> toResultSetIterableMap(String sql, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
boolean error = true;
PreparedStatement ps = null;
ResultSet rs = null;
ResultSetIterable<Map<String, V>> ret = null;
try {
ps = conn.prepareStatement(sql);
rs = this.toResultSet(ps, bindObjects);
ret = cm.toResultSetIterableMap(rs, componentType, mapValType).setPreparedStatementToClose(ps);
error = false;
return ret;
} finally {
if (error) {
tryClose(ret);
tryClose(rs);
tryClose(ps);
}
}
}
// these are standard getters
public ResultSetMapper getCustomResultSetMapper() {
@ -364,6 +408,14 @@ public class QueryMapper implements Closeable {
}
}
public <T> ResultSetIterable<T> toResultSetIterable(PreparedStatement ps, Class<T> componentType, final Object... bindObjects) throws SQLException {
return cm.toResultSetIterable(bindExecute(ps, bindObjects), componentType);
}
public <T extends Map<String, V>, V> ResultSetIterable<Map<String, V>> toResultSetIterableMap(PreparedStatement ps, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toResultSetIterableMap(bindExecute(ps, bindObjects), componentType, mapValType);
}
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(PreparedStatement ps, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toSingleMap(bindExecute(ps, bindObjects), componentType, mapValType);
}

View File

@ -19,8 +19,11 @@ package com.moparisthebest.jdbc;
* $Header:$
*/
import com.moparisthebest.jdbc.util.ResultSetIterable;
import java.lang.ref.SoftReference;
import java.lang.reflect.*;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
@ -122,12 +125,22 @@ public class ResultSetMapper implements RowMapperProvider {
if (rs.next())
ret = getRowMapper(rs, componentType, cal, mapValType, null).mapRowToReturnType();
} catch (SQLException e) {
// ignore
// ignore // todo: this looks crazy dangerous look into it...
}
tryClose(rs);
return ret == null ? RowToObjectMapper.fixNull(componentType) : ret;
}
protected <T> ResultSetIterable<T> privToResultSetIterable(ResultSet rs, Class<T> componentType, Calendar cal, Class<?> mapValType) {
try {
return ResultSetIterable.getResultSetIterable(rs,
rs.next() ? getRowMapper(rs, componentType, cal, mapValType, null).getResultSetToObject() : null,
cal);
} catch (SQLException e) {
throw new MapperException("cannot create ResultSetIterable", e);
}
}
protected <T extends Collection<E>, E> T privToCollection(ResultSet rs, final Class<T> collectionType, Class<E> componentType, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
return privToCollection(rs, instantiateClass(collectionType, ArrayList.class), componentType, arrayMaxLength, cal, mapValType);
}
@ -437,6 +450,15 @@ public class ResultSetMapper implements RowMapperProvider {
return privToObject(rs, componentType, cal, null);
}
public <T> ResultSetIterable<T> toResultSetIterable(ResultSet rs, Class<T> componentType, Calendar cal) {
return privToResultSetIterable(rs, componentType, cal, null);
}
@SuppressWarnings("unchecked")
public <T extends Map<String, V>, V> ResultSetIterable<Map<String, V>> toResultSetIterableMap(ResultSet rs, Class<T> componentType, Class<V> mapValType, Calendar cal) {
return (ResultSetIterable<Map<String, V>>)privToResultSetIterable(rs, componentType, cal, mapValType);
}
public <T extends Collection<E>, E> T toCollection(ResultSet rs, final Class<T> collectionType, Class<E> componentType, int arrayMaxLength, Calendar cal) {
return privToCollection(rs, collectionType, componentType, arrayMaxLength, cal, null);
}
@ -607,6 +629,14 @@ public class ResultSetMapper implements RowMapperProvider {
return this.toObject(rs, componentType, cal);
}
public <T> ResultSetIterable<T> toResultSetIterable(ResultSet rs, Class<T> componentType) {
return this.toResultSetIterable(rs, componentType, cal);
}
public <T extends Map<String, V>, V> ResultSetIterable<Map<String, V>> toResultSetIterableMap(ResultSet rs, Class<T> componentType, Class<V> mapValType) {
return this.toResultSetIterableMap(rs, componentType, mapValType, cal);
}
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(ResultSet rs, Class<T> componentType, Class<V> mapValType) {
return this.toSingleMap(rs, componentType, mapValType, cal);
}

View File

@ -1,5 +1,7 @@
package com.moparisthebest.jdbc;
import com.moparisthebest.jdbc.util.ResultSetToObject;
import java.sql.SQLException;
/**
@ -18,4 +20,6 @@ public interface RowMapper<K,T> {
* @throws MapperException if _mapKeyType is null
*/
K getMapKey() throws SQLException;
ResultSetToObject<T> getResultSetToObject();
}

View File

@ -1,15 +1,18 @@
package com.moparisthebest.jdbc;
import com.moparisthebest.jdbc.dto.*;
import com.moparisthebest.jdbc.util.ResultSetIterable;
import org.junit.*;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.*;
import static com.moparisthebest.jdbc.TryClose.tryClose;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@ -25,6 +28,11 @@ public class QueryMapperTest {
public static final Boss fieldBoss1 = new FieldBoss(2, new Date(0), "Second", "Person", "Finance", "Second");
public static final Boss fieldBoss2 = new FieldBoss(3, new Date(0), "Third", "Person", "Finance", null);
public static final Boss fieldBoss3 = new FieldBoss(4, new Date(0), null, "Person", "Finance", "Fourth");
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[] people = new Person[]{fieldPerson1, fieldPerson2, fieldPerson3};
public static final Boss[] bosses =new Boss[]{fieldBoss1, fieldBoss2, fieldBoss3};
public static final Person setPerson1 = new SetPerson(fieldPerson1);
public static final Boss setBoss1 = new SetBoss(fieldBoss1);
@ -70,9 +78,9 @@ public class QueryMapperTest {
qm = new QueryMapper(conn);
qm.executeUpdate("CREATE TABLE person (person_no NUMERIC, first_name VARCHAR(40), last_name VARCHAR(40), birth_date TIMESTAMP)");
qm.executeUpdate("CREATE TABLE boss (person_no NUMERIC, department VARCHAR(40))");
for (final Person person : new Person[]{fieldPerson1})
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());
for (final Boss boss : new Boss[]{fieldBoss1, fieldBoss2, fieldBoss3}) {
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 boss (person_no, department) VALUES (?, ?)", boss.getPersonNo(), boss.getDepartment());
}
@ -249,7 +257,7 @@ public class QueryMapperTest {
@Test
public void testSelectArrayMap() throws Throwable {
final List<Map<String, String>> arrayMap = getListMap();
Assert.assertArrayEquals(arrayMap.toArray(new Map[arrayMap.size()]), qm.toArrayMap("SELECT first_name, last_name FROM person WHERE person_no < 4", arrayMap.get(0).getClass(), String.class));
assertArrayEquals(arrayMap.toArray(new Map[arrayMap.size()]), qm.toArrayMap("SELECT first_name, last_name FROM person WHERE person_no < 4", arrayMap.get(0).getClass(), String.class));
}
@Test
@ -304,19 +312,19 @@ public class QueryMapperTest {
@Test
public void testSelectLongObjectArray() throws Throwable {
final Long[] expected = {fieldPerson1.getPersonNo()};
Assert.assertArrayEquals(expected, qm.toArray("SELECT person_no FROM person WHERE person_no = ?", Long.class, expected[0]));
assertArrayEquals(expected, qm.toArray("SELECT person_no FROM person WHERE person_no = ?", Long.class, expected[0]));
}
@Test
public void testSelectObjectArray() throws Throwable {
final Long[] arr = {1L, 2L, 3L};
Assert.assertArrayEquals(arr, qm.toObject("SELECT 1, 2, 3 FROM person WHERE person_no = ?", Long[].class, fieldPerson1.getPersonNo()));
assertArrayEquals(arr, qm.toObject("SELECT 1, 2, 3 FROM person WHERE person_no = ?", Long[].class, fieldPerson1.getPersonNo()));
}
@Test
public void testSelectPrimitiveArray() throws Throwable {
final long[] arr = {1L, 2L, 3L};
Assert.assertArrayEquals(arr, qm.toObject("SELECT 1, 2, 3 FROM person WHERE person_no = ?", long[].class, fieldPerson1.getPersonNo()));
assertArrayEquals(arr, qm.toObject("SELECT 1, 2, 3 FROM person WHERE person_no = ?", long[].class, fieldPerson1.getPersonNo()));
}
@Test(expected = com.moparisthebest.jdbc.MapperException.class)
@ -371,4 +379,31 @@ public class QueryMapperTest {
assertNull(map.get("TOM"));
}
}
@Test
public void testList() throws SQLException {
final List<FieldPerson> fromDb = qm.toList("SELECT * from person WHERE person_no IN (?,?,?) ORDER BY person_no",
FieldPerson.class, people[0].getPersonNo(), people[1].getPersonNo(), people[2].getPersonNo());
assertArrayEquals(people, fromDb.toArray());
}
@Test
public void testListQueryMapperList() throws SQLException {
final ListQueryMapper lqm = new ListQueryMapper(qm);
final List<FieldPerson> fromDb = lqm.toList("SELECT * from person WHERE " + ListQueryMapper.inListReplace + " ORDER BY person_no",
FieldPerson.class, lqm.inList("person_no", Arrays.asList(people[0].getPersonNo(), people[1].getPersonNo(), people[2].getPersonNo())));
assertArrayEquals(people, fromDb.toArray());
lqm.close();
}
@Test
public void testResultSetIterable() throws SQLException {
final ResultSetIterable<FieldPerson> rsi = qm.toResultSetIterable("SELECT * from person WHERE person_no IN (?,?,?) ORDER BY person_no",
FieldPerson.class, people[0].getPersonNo(), people[1].getPersonNo(), people[2].getPersonNo());
final List<FieldPerson> fromDb = new ArrayList<FieldPerson>();
for(final FieldPerson fieldPerson : rsi)
fromDb.add(fieldPerson);
rsi.close();
assertArrayEquals(people, fromDb.toArray());
}
}