java. sql .SQLException: набор результатов закрывается в Firebird при выполнении двух операторов - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь сделать 2 запроса из базы данных Firebird 2.5, я использую 2 отдельных объекта Statement, но когда во второй программе запроса пытаются использовать данные из первого запроса, появляется ошибка java.sql.SQLException: The result set is closed.

conn = DriverManager.getConnection(
                    strURL,
                    strUser, strPassword);


            if (conn == null) {
                System.err.println("Could not connect to database");
            }

            Statement stmt = conn.createStatement();
            Statement statement = conn.createStatement();

            ResultSet rs = stmt.executeQuery(strSQL);
            ResultSet rs2 = null;

            try {
                while (rs.next()) {
                    String strSQL2 = "SELECT PATIENT_NAME_R, PATIENT_DOB, PATIENT_ID, PATIENT_SEX, PATIENT_ADDRESS_CITY, PATIENT_ADDRESS_SHF FROM PATIENTS WHERE PATIENT_UID = " + rs.getObject(1);
                    rs2 = statement.executeQuery(strSQL2);
                    try {
                        while (rs2.next()) {
                            System.out.println("СПРАВКА");
                            System.out.println("Ф.И.О.: " + rs2.getObject(1).toString().trim() + " Дата рождения: " + rs2.getObject(2));
                            System.out.println("СНИЛС: " + rs2.getObject(3));
                            System.out.println("Адрес: " + rs2.getObject(5) + " " + rs2.getObject(6));
                            System.out.println("Врач: " + rs.getString("STUDY_MD"));
                            System.out.println("----------------------------------------------------------------");
                        }
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

В то время как (rs2.next ()) в строке System.out.println ("Врач:" + rs.getString ("STUDY_MD")) я получаю ошибку

java.sql.SQLException: The result set is closed
at org.firebirdsql.jdbc.AbstractResultSet.checkOpen(AbstractResultSet.java:297)
at org.firebirdsql.jdbc.AbstractResultSet.getField(AbstractResultSet.java:788)
at org.firebirdsql.jdbc.AbstractResultSet.getString(AbstractResultSet.java:844)
at sample.Main$MedicalCert.run(Main.java:156)
at java.lang.Thread.run(Thread.java:748)

1 Ответ

1 голос
/ 23 января 2020

Проблема в том, что вы выполняете два оператора для соединения, которое находится в режиме автоматической фиксации. В режиме автоматической фиксации при выполнении оператора наборы результатов, созданные другими операторами, закрываются.

Как описано в спецификации JDB C 4.3 , в разделе 15.2.5 Закрытие ResultSet объекта :

A ResultSet объект неявно закрывается, когда

  • Повторно выполненный связанный Statement объект
  • ResultSet создается с Удерживаемостью CLOSE_CURSORS_AT_COMMIT и происходит неявное или явное принятие

С Jaybird (драйвер Firebird JDB C) вы есть три варианта:

  1. Отключить автоматическую фиксацию перед выполнением операторов:

    conn.setAutoCommit(false);
    
  2. Сделать первый оператор доступным для фиксации, выполнив as

    Statement stmt = conn.createStatement(
            ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
            ResultSet.HOLD_CURSORS_OVER_COMMIT);
    

    Это приведет к тому, что полученный результат останется открытым после фиксации (automati c). Имейте в виду, однако, что в этом режиме Jaybird будет извлекать весь набор результатов в память, а не извлекать его партиями.

  3. Как и в предыдущем варианте, вы можете настроить Jaybird по умолчанию на использование holdable наборы результатов, указав свойство соединения defaultResultSetHoldable set. См. Также Наборы удерживаемых результатов по умолчанию . Установка этого свойства повлияет на все операторы и результирующие наборы.

Первый вариант предпочтительнее.

Кроме того, я настоятельно рекомендую вам начать использовать try-with-resources : ваш текущий код уязвим для утечек ресурсов.

Как указано в комментариях Kayaman, вам следует подумать о переписывании ваших запросов, чтобы это был всего лишь один запрос. В настоящее время вы создаете так называемую проблему запроса N + 1 (выполнение оператора, а затем для каждой строки этого оператора выполнение другого оператора). Использование соединения в вашем запросе позволит вам выполнить его как один запрос. И как предупреждение, ваш запрос уязвим для сохраненной SQL инъекции, потому что вы объединяете значение в строку запроса.

...