Если сравнение должно быть выполнено в контексте тестирования, используйте assertCountEqual(a, b)
(py>=3.2
) и assertItemsEqual(a, b)
(2.7<=py<3.2
).
Работает и с последовательностями неотображаемых объектов.
В JDBC действительно нет прямого способа сделать это. Некоторые драйверы JDBC, похоже, поддерживают PreparedStatement#setArray()
на IN
клаузе. Я только не уверен, какие именно.
Можно просто использовать вспомогательный метод с String#join()
и Collections#nCopies()
для генерации заполнителей для IN
и другой вспомогательный метод для установки всех значений в цикле с PreparedStatement#setObject()
.
public static String preparePlaceHolders(int length) {
return String.join(",", Collections.nCopies(length, "?"));
}
public static void setValues(PreparedStatement preparedStatement, Object... values) throws SQLException {
for (int i = 0; i < values.length; i++) {
preparedStatement.setObject(i + 1, values[i]);
}
}
Вот как это можно использовать:
private static final String SQL_FIND = "SELECT id, name, value FROM entity WHERE id IN (%s)";
public List<Entity> find(Set<Long> ids) throws SQLException {
List<Entity> entities = new ArrayList<Entity>();
String sql = String.format(SQL_FIND, preparePlaceHolders(ids.size()));
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(sql);
) {
setValues(statement, ids.toArray());
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
entities.add(map(resultSet));
}
}
}
return entities;
}
private static Entity map(ResultSet resultSet) throws SQLException {
Enitity entity = new Entity();
entity.setId(resultSet.getLong("id"));
entity.setName(resultSet.getString("name"));
entity.setValue(resultSet.getInt("value"));
return entity;
}
Обратите внимание, что некоторые базы данных имеют ограничение на допустимое количество значений в клаузе IN
. Например, Oracle имеет такое ограничение на 1000 элементов.
Я решил эту проблему, построив строку SQL с таким количеством ?
, сколько мне нужно искать.
SELECT * FROM MYTABLE WHERE MYCOL in (?,?,?,?)
Сначала я искал тип массива, который можно передать в оператор, но все типы массивов JDBC зависят от производителя. Поэтому я остановился на кратном ?
.
AFAIK, в JDBC нет стандартной поддержки для обработки коллекций как параметров. Было бы здорово, если бы вы могли просто перейти в список, и он был бы расширен.
Доступ JDBC от Spring поддерживает передачу коллекций в качестве параметров. Вы можете посмотреть, как это делается для вдохновения в безопасном кодировании.
См. Автоматически расширяемые коллекции как параметры JDBC
(В статье сначала обсуждается Hibernate, а затем обсуждается JDBC.)
Один из способов, который я могу придумать, это использовать java.sql.PreparedStatement и немного подправить жюри
PreparedStatement preparedStmt = conn.prepareStatement("SELECT * FROM MYTABLE WHERE MYCOL in (?)");
... а затем ...
preparedStmt.setString(1, [ваши строковые параметры]);
http://java.sun.com/docs/books/tutorial/jdbc/basics/prepared.html