Там нет действительно не простой способ сделать это в 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 ... – Uri
Кроме того, если это что-то вроде Oracle, ему придется перепрофилировать большинство операторов. – orbfish