Add ListQueryMapper.notInList() and tests

This commit is contained in:
Travis Burtrum 2018-05-22 23:09:57 -04:00
parent d0a912a83e
commit 81b91d43e8
12 changed files with 71 additions and 12 deletions

View File

@ -73,7 +73,7 @@ public class InListUtil {
} }
public static <T> String toNotInList(final String fieldName, final Collection<T> items) { public static <T> String toNotInList(final String fieldName, final Collection<T> items) {
return toInList(fieldName, items, defaultMaxSize); return toNotInList(fieldName, items, defaultMaxSize);
} }
public static <T> String toInList(final String fieldName, final T[] items) { public static <T> String toInList(final String fieldName, final T[] items) {
@ -81,6 +81,6 @@ public class InListUtil {
} }
public static <T> String toNotInList(final String fieldName, final T[] items) { public static <T> String toNotInList(final String fieldName, final T[] items) {
return toInList(fieldName, Arrays.asList(items), defaultMaxSize); return toNotInList(fieldName, Arrays.asList(items), defaultMaxSize);
} }
} }

View File

@ -29,10 +29,14 @@ public class ArrayInList implements InList {
this(JdbcMapper.DatabaseType.ANY.arrayNumberTypeName, JdbcMapper.DatabaseType.ANY.arrayStringTypeName); this(JdbcMapper.DatabaseType.ANY.arrayNumberTypeName, JdbcMapper.DatabaseType.ANY.arrayStringTypeName);
} }
protected String columnAppend(final String columnName) { protected String columnAppendIn(final String columnName) {
return "(" + columnName + " = ANY(?))"; return "(" + columnName + " = ANY(?))";
} }
protected String columnAppendNotIn(final String columnName) {
return "(" + columnName + " != ANY(?))";
}
public Array toArray(final Connection conn, final String typeName, final Object[] elements) throws SQLException { public Array toArray(final Connection conn, final String typeName, final Object[] elements) throws SQLException {
return conn.createArrayOf(typeName, elements); return conn.createArrayOf(typeName, elements);
} }
@ -46,8 +50,15 @@ public class ArrayInList implements InList {
} }
public <T> InListObject inList(final Connection conn, final String columnName, final Collection<T> values) throws SQLException { public <T> InListObject inList(final Connection conn, final String columnName, final Collection<T> values) throws SQLException {
return values == null || values.isEmpty() ? InListObject.empty : new ArrayListObject( return values == null || values.isEmpty() ? InListObject.inEmpty : new ArrayListObject(
columnAppend(columnName), columnAppendIn(columnName),
toArray(conn, values)
);
}
public <T> InListObject notInList(final Connection conn, final String columnName, final Collection<T> values) throws SQLException {
return values == null || values.isEmpty() ? InListObject.notInEmpty : new ArrayListObject(
columnAppendNotIn(columnName),
toArray(conn, values) toArray(conn, values)
); );
} }

View File

@ -5,6 +5,7 @@ import java.util.*;
import static com.moparisthebest.jdbc.util.InListUtil.defaultMaxSize; import static com.moparisthebest.jdbc.util.InListUtil.defaultMaxSize;
import static com.moparisthebest.jdbc.util.InListUtil.toInList; import static com.moparisthebest.jdbc.util.InListUtil.toInList;
import static com.moparisthebest.jdbc.util.InListUtil.toNotInList;
/** /**
* Created by mopar on 4/29/15. * Created by mopar on 4/29/15.
@ -28,12 +29,19 @@ public class BindInList implements InList {
} }
public <T> InListObject inList(final Connection conn, final String columnName, final Collection<T> values) { public <T> InListObject inList(final Connection conn, final String columnName, final Collection<T> values) {
return values == null || values.isEmpty() ? InListObject.empty : new BindInListObject( return values == null || values.isEmpty() ? InListObject.inEmpty : new BindInListObject(
toInList(columnName, values, this.maxSize), toInList(columnName, values, this.maxSize),
values.toArray() values.toArray()
); );
} }
public <T> InListObject notInList(final Connection conn, final String columnName, final Collection<T> values) {
return values == null || values.isEmpty() ? InListObject.notInEmpty : new BindInListObject(
toNotInList(columnName, values, this.maxSize),
values.toArray()
);
}
class BindInListObject extends InListObject { class BindInListObject extends InListObject {
private final Object[] bindObjects; private final Object[] bindObjects;

View File

@ -18,8 +18,17 @@ public interface InList {
*/ */
public <T> InListObject inList(final Connection conn, final String columnName, final Collection<T> values) throws SQLException; public <T> InListObject inList(final Connection conn, final String columnName, final Collection<T> values) throws SQLException;
/**
* Returns an Object who's .toString returns a String for a query, and QueryMapper knows how to bind to a PreparedStatement
* @param columnName Column name for query
* @param values values for not in list
* @return object
*/
public <T> InListObject notInList(final Connection conn, final String columnName, final Collection<T> values) throws SQLException;
class InListObject { class InListObject {
static final InListObject empty = new InListObject("(0=1)"); static final InListObject inEmpty = new InListObject("(0=1)");
static final InListObject notInEmpty = new InListObject("(1=1)");
private final String sql; private final String sql;

View File

@ -109,6 +109,10 @@ public class ListQueryMapper extends QueryMapper {
return this.inList.inList(delegate.conn, columnName, values); return this.inList.inList(delegate.conn, columnName, values);
} }
public <T> InList.InListObject notInList(final String columnName, final Collection<T> values) throws SQLException {
return this.inList.notInList(delegate.conn, columnName, values);
}
// these update the database // these update the database
@Override @Override

View File

@ -44,10 +44,14 @@ public class OracleArrayInList extends ArrayInList {
this(JdbcMapper.DatabaseType.ORACLE.arrayNumberTypeName, JdbcMapper.DatabaseType.ORACLE.arrayStringTypeName); this(JdbcMapper.DatabaseType.ORACLE.arrayNumberTypeName, JdbcMapper.DatabaseType.ORACLE.arrayStringTypeName);
} }
protected String columnAppend(final String columnName) { protected String columnAppendIn(final String columnName) {
return "(" + columnName + " IN(select column_value from table(?)))"; return "(" + columnName + " IN(select column_value from table(?)))";
} }
protected String columnAppendNotIn(final String columnName) {
return "(" + columnName + " NOT IN(select column_value from table(?)))";
}
public Array toArray(final Connection conn, final String typeName, final Object[] elements) throws SQLException { public Array toArray(final Connection conn, final String typeName, final Object[] elements) throws SQLException {
//return conn.unwrap(oracle.jdbc.OracleConnection.class).createOracleArray(typeName, elements); //return conn.unwrap(oracle.jdbc.OracleConnection.class).createOracleArray(typeName, elements);
try { try {

View File

@ -238,7 +238,7 @@ public class QueryMapper implements JdbcMapper {
if (bindObjects != null && bindObjects.length > 0) { if (bindObjects != null && bindObjects.length > 0) {
for (Object o : bindObjects) { for (Object o : bindObjects) {
if (o != null) { if (o != null) {
if (o == InList.InListObject.empty || o == noBind) { if (o == InList.InListObject.inEmpty || o == InList.InListObject.notInEmpty || o == noBind) {
continue; // ignore continue; // ignore
} else if (o instanceof BindInList.BindInListObject) { } else if (o instanceof BindInList.BindInListObject) {
if (((BindInList.BindInListObject) o).getBindObjects() != null) if (((BindInList.BindInListObject) o).getBindObjects() != null)

View File

@ -22,7 +22,11 @@ public class UnNestArrayInList extends ArrayInList {
this(JdbcMapper.DatabaseType.UNNEST.arrayNumberTypeName, JdbcMapper.DatabaseType.UNNEST.arrayStringTypeName); this(JdbcMapper.DatabaseType.UNNEST.arrayNumberTypeName, JdbcMapper.DatabaseType.UNNEST.arrayStringTypeName);
} }
protected String columnAppend(final String columnName) { protected String columnAppendIn(final String columnName) {
return "(" + columnName + " IN(UNNEST(?)))"; return "(" + columnName + " IN(UNNEST(?)))";
} }
protected String columnAppendNotIn(final String columnName) {
return "(" + columnName + " NOT IN(UNNEST(?)))";
}
} }

View File

@ -255,4 +255,7 @@ public interface QmDao extends JdbcMapper {
@SQL("SELECT person_no, first_name, last_name, birth_date from person WHERE {person_no IN personNos} AND ({first_name IN names} OR {last_name IN names}) ORDER BY person_no") @SQL("SELECT person_no, first_name, last_name, birth_date from person WHERE {person_no IN personNos} AND ({first_name IN names} OR {last_name IN names}) ORDER BY person_no")
List<FieldPerson> getFieldPeopleByName(List<Long> personNos, List<String> names) throws SQLException; List<FieldPerson> getFieldPeopleByName(List<Long> personNos, List<String> names) throws SQLException;
@SQL("SELECT person_no, first_name, last_name, birth_date from person WHERE {person_no NOT IN personNos} ORDER BY person_no")
List<FieldPerson> getFieldPeopleNotIn(List<Long> personNos) throws SQLException;
} }

View File

@ -62,11 +62,11 @@ public class QueryMapperQmDao implements QmDao {
Collection<Class<?>> no = new ArrayList<Class<?>>(); Collection<Class<?>> no = new ArrayList<Class<?>>();
for(final String connectionClassName : new String[]{ for(final String connectionClassName : new String[]{
"org.apache.derby.iapi.jdbc.EngineConnection" "org.apache.derby.iapi.jdbc.EngineConnection"
//, "org.hsqldb.jdbc.JDBCConnection" // does not support ArrayInList but *does* support UnNestArrayInList , "org.hsqldb.jdbc.JDBCConnection" // does not support ArrayInList but *does* support UnNestArrayInList
, "org.sqlite.jdbc3.JDBC3Connection" , "org.sqlite.jdbc3.JDBC3Connection"
, "org.mariadb.jdbc.MariaDbConnection" , "org.mariadb.jdbc.MariaDbConnection"
, "com.microsoft.sqlserver.jdbc.ISQLServerConnection" , "com.microsoft.sqlserver.jdbc.ISQLServerConnection"
//, "oracle.jdbc.OracleConnection" // does not support ArrayInList but *does* support OracleArrayInList , "oracle.jdbc.OracleConnection" // does not support ArrayInList but *does* support OracleArrayInList
// h2 doesn't support this with java6 either... // h2 doesn't support this with java6 either...
/*IFJAVA6_START /*IFJAVA6_START
, "org.h2.jdbc.JdbcConnection" , "org.h2.jdbc.JdbcConnection"
@ -475,4 +475,9 @@ public class QueryMapperQmDao implements QmDao {
lqm.inList("last_name", names) lqm.inList("last_name", names)
); );
} }
@Override
public List<FieldPerson> getFieldPeopleNotIn(final List<Long> personNos) throws SQLException {
return lqm.toList("SELECT * from person WHERE " + inListReplace + " ORDER BY person_no", FieldPerson.class, lqm.notInList("person_no", personNos));
}
} }

View File

@ -354,4 +354,9 @@ public class QueryMapperTypeQmDao extends QueryMapperQmDao {
lqm.inList("last_name", names) lqm.inList("last_name", names)
); );
} }
@Override
public List<FieldPerson> getFieldPeopleNotIn(final List<Long> personNos) throws SQLException {
return lqm.toType("SELECT * from person WHERE " + ListQueryMapper.inListReplace + " ORDER BY person_no", new TypeReference<List<FieldPerson>>() {}, lqm.notInList("person_no", personNos));
}
} }

View File

@ -682,4 +682,10 @@ public class QueryMapperTest {
Arrays.asList(people[0].getFirstName(), people[1].getFirstName(), people[2].getFirstName())); Arrays.asList(people[0].getFirstName(), people[1].getFirstName(), people[2].getFirstName()));
assertArrayEquals(people, fromDb.toArray()); assertArrayEquals(people, fromDb.toArray());
} }
@Test
public void testListQueryMapperListNotIn() throws SQLException {
final List<FieldPerson> fromDb = qm.getFieldPeopleNotIn(Arrays.asList(bosses[0].getPersonNo(), bosses[1].getPersonNo(), bosses[2].getPersonNo()));
assertArrayEquals(people, fromDb.toArray());
}
} }