Java: JDBC ResultSet не заполнен всеми результатами запроса - PullRequest
1 голос
/ 10 февраля 2010

Я работаю над тем, чтобы Java-бины нашей системы могли использовать предложение SQL IN при выполнении запросов через базу данных, но столкнулись с недоумением.

Я строю SQL-запрос для PreparedStatement по следующему универсальному шаблону:

select [column names] 
from [table name]
where [a column name] IN (?, ? , ?, ..., ?)

Символ ..., представляет любое количество символов? В зависимости от количества значений, которые пользователь решает встроить в предложение IN. Я запускаю цикл, чтобы получить их в строку запроса.

Здесь я использую метод SetString (idx, String) класса PreparedStatement, перебираю список значений и запускаюсь из индекса 1 - # значений.

PreparedStatement запускает запрос с помощью метода executeQuery (), и возвращенный ResultSet кажется неверным.

В конкретном случае, используя 4 значения, когда я беру запрос в PreparedStatement в SQL и заменяю каждое? с точными значениями в '', я получаю 3 результата (так как одно из значений намеренно отсутствует в БД).

ResultSet, с другой стороны, имеет только 1 строку в своем наборе, и эта строка всегда соответствует первой? параметр в предложении IN.

Я даже пытался подделать предложение IN с помощью ([имя столбца] =? ИЛИ [имя столбца] =? ... ИЛИ столбца имя] =?), Но такая же проблема возникает и здесь.

Есть идеи, что здесь происходит? Кстати, подключаясь к базе данных Oracle.

Журналы:

2010-02-10 11:16:28,505 DEBUG  basic.BasicCursor - Preparing statement SELECT MERCHANT_ID, M_NAME, M_AUTHEN, M_ADMIN_AUTHEN, M_CONTACT_ADDR, M_PAYMENT_ADDR, M_HAS_MPROXY, M_DISABLED, M_FREETEXT, TXN_ID, M_TAX_NAME, M_TAX_RATE, MERCHANT_PARENT_ID, MERCHANT_ROOT_ID, RESERVED_1, RESERVED_2, RESERVED_3, RESERVED_4, EMAIL, LOGICAL_TYPE, CHANNEL_MASK FROM MERCHANT0 WHERE MERCHANT_ID IN (?, ?, ?, ?)  ORDER BY MERCHANT_ID
2010-02-10 11:16:28,505 DEBUG  basic.BasicCursor - Adding string  to slot 1: 6172222222
2010-02-10 11:16:28,505 DEBUG  basic.BasicCursor - Adding string  to slot 2:  6177740603
2010-02-10 11:16:28,505 DEBUG  basic.BasicCursor - Adding string  to slot 3:  6177740602
2010-02-10 11:16:28,505 DEBUG  basic.BasicCursor - Adding string  to slot 4:  6172441111
2010-02-10 11:16:28,512 DEBUG  basic.BasicCursor - scanCursor() calling... checking for next row. Current row is : 0
2010-02-10 11:16:28,512 DEBUG  basic.BasicCursor - scanCursor() called, hit
2010-02-10 11:16:28,512 DEBUG  basic.BasicCursor - scanCursor() got object 6172222222
2010-02-10 11:16:28,512 DEBUG  basic.BasicCursor - scanCursor() calling... checking for next row. Current row is : 1
2010-02-10 11:16:28,512 DEBUG  basic.BasicCursor - scanCursor() called, not hit
2010-02-10 11:16:28,505 DEBUG  basic.BasicCursor - The size of variables list = 4

РЕДАКТИРОВАТЬ: обнаружены проблемы с PreparedStatement. Я оставлю это как упражнение тем, кому интересно разобраться. Это видно в журнале операторов выше. К сожалению, теперь моя проблема связана с каким-то раздражающим проприетарным кодом, который у нас есть, который ограничивает строки из ожидаемого в настоящее время ResultSet отображением только 1 записи в любом случае. Вздох

Ответы [ 2 ]

3 голосов
/ 10 февраля 2010
  • перепроверьте полный построенный запрос и сравните, что это действительно то, что вы ожидаете
  • перепроверьте, что вы действительно вызываете setString() с различными значениями для индекса и строки и что вы не используете одно и то же значение снова и снова
  • перепроверьте, что вы не вызываете next() в ResultSet более одного раза за итерацию цикла.
  • изменить: System.out.println() и проверить (и, возможно, опубликовать) следующее:
    • Полная строка запроса SQL
    • toString() вновь созданного PreparedStatement
    • оба параметра каждого setString() вызова и toString() PreparedStatement каждый раз, когда вы вызываете setString()
    • возвращаемое значение next() каждый раз, когда вы вызываете его
0 голосов
/ 10 февраля 2010

Итак, вы использовали эту конструкцию?

private static final String SQL = "SELECT * FROM MERCHANT0 WHERE MERCHANT_ID IN (%s)";

public List<Merchant> list(List<Long> ids) {
    StringBuilder placeHolders = new StringBuilder();
    for (int i = 0; i < ids.size(); i++) {
        placeHolders.append("?");
        if (i + 1 < ids.size()) {
            placeHolders.append(",");
        }
    }
    String sql = String.format(SQL, placeHolders.toString());

    // ...

    try {
        // ...

        preparedStatement = connection.prepareStatement(SQL);
        for (int i = 0; i < ids.size(); i++) {
            preparedStatement.setLong(i + 1, ids.get(i));
        }
        resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            Long id = resultSet.getLong("MERCHANT_ID");
            System.out.println(id); // Should print all of the `ids`.
        }

        // ...

Помимо того, что Oracle имеет ограничение в 1000 значений внутри предложения IN, это должно сработать.

...