Каков наилучший подход с использованием JDBC для параметризации предложения IN? [Дубликат]

Если сравнение должно быть выполнено в контексте тестирования, используйте assertCountEqual(a, b) (py>=3.2) и assertItemsEqual(a, b) (2.7<=py<3.2).

Работает и с последовательностями неотображаемых объектов.

37
задан Community 23 May 2017 в 12:18
поделиться

4 ответа

В 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 элементов.

43
ответ дан 27 November 2019 в 04:38
поделиться

Я решил эту проблему, построив строку SQL с таким количеством ? , сколько мне нужно искать.

SELECT * FROM MYTABLE WHERE MYCOL in (?,?,?,?)

Сначала я искал тип массива, который можно передать в оператор, но все типы массивов JDBC зависят от производителя. Поэтому я остановился на кратном ? .

4
ответ дан 27 November 2019 в 04:38
поделиться

AFAIK, в JDBC нет стандартной поддержки для обработки коллекций как параметров. Было бы здорово, если бы вы могли просто перейти в список, и он был бы расширен.

Доступ JDBC от Spring поддерживает передачу коллекций в качестве параметров. Вы можете посмотреть, как это делается для вдохновения в безопасном кодировании.

См. Автоматически расширяемые коллекции как параметры JDBC

(В статье сначала обсуждается Hibernate, а затем обсуждается JDBC.)

1
ответ дан 27 November 2019 в 04:38
поделиться

Один из способов, который я могу придумать, это использовать 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

-2
ответ дан 27 November 2019 в 04:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: