При попытке выполнить запрос к базе данных с помощью PreparedStatement ResultSet снова закрывается, когда не следует - PullRequest
1 голос
/ 12 декабря 2011

Я пытаюсь запросить мою базу данных, используя подготовленное утверждение. Изначально у меня было это:

public ResultSet preparedQueryContactsWhereAccount(String accountName) throws SQLException {
    PreparedStatement statment = null;
    ResultSet rs = null;
    String statString = "SELECT * FROM contacts WHERE account_name = ?";

    try {
        statment = mConn.prepareStatement(statString);
        statment.setString(1, accountName);
        rs = statment.executeQuery();
    } catch(SQLException e) {
        e.printStackTrace();
    }
    if(statment != null) {
        statment.close();
    }
    return rs;
}

Однако это вернет закрытый ResultSet. Я немного прочитал и обнаружил, что иногда, когда оператор закрывается, его ResultSets также может быть закрыт. Итак, я попробовал это:

public MasterEntry preparedQueryContactsWhereAccount(String accountName, MasterEntry entry) throws SQLException, IllegalAccessException {
    PreparedStatement prepStat = null;
    ResultSet rs = null;
    String statString = "SELECT * FROM contacts WHERE account_name = ?";

    try {
        prepStat = mConn.prepareStatement(statString);
        prepStat.setString(1, accountName);
        rs = prepStat.executeQuery();
    } catch(Exception e) {
        e.printStackTrace();
        System.err.println("Statement failed.");
    }
    if(rs.isClosed()) {
        System.out.println("fail");
        throw new IllegalAccessException("closed");
    }
    else {
        entry.setmFirstName(rs.getString("first_name"));
        entry.setmLastName(rs.getString("last_name"));
        entry.setmEmail(rs.getString("email_address"));
        rs.close();
        prepStat.close();
    }
    return entry;

}

Просто немного реорганизовал процесс, чтобы все данные ResultSet могли обрабатываться внутри метода. Это приводит к тому, что IllegalAccessException, которое вы видите там, ResultSet закрыт.

Я попытался выполнить этот же запрос более простым способом (который не так безопасен и не может обрабатывать такие символы, как апострофы):

public ResultSet makeQuery(String query) {
    ResultSet rs = null;
    try {
        rs = mStat.executeQuery(query);
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Problem in query: " + query);
    }
    return rs;
}

Где запрос равен "SELECT * FROM contacts WHERE account_name = '" + accountName + "'"

Строка accountName String, которую я использовал в методе prepareQuery. Этот способ работает нормально, за исключением, конечно, любой accountName с апострофом в нем не удастся. Я действительно хотел бы сделать это с готовым заявлением, но я просто не могу понять это. Любой совет? Большое спасибо.

Ответы [ 3 ]

2 голосов
/ 13 декабря 2011

Похоже, ваш код в порядке, но вы пропускаете команду rs.next ().Вы пытаетесь прочитать набор результатов, который не был установлен для определенной строки, и, таким образом, вы получаете исключение IllegalStateException.

1 голос
/ 13 декабря 2011

Я рекомендую вам не делать этого.

Вместо того, чтобы возвращать свой ResultSet, вы должны немедленно пройтись по нему, извлечь все результаты и передать их чему-то другому. Затем он должен быть закрыт.

Передача таких вещей, как Statements, ResultSets и Connections, ОБЯЗАНА в конечном итоге вызвать утечку ресурсов, не говоря уже о создании ненужной сложности в вашем коде, пытаясь избежать этих утечек. Все они должны быть открыты, использованы и немедленно закрыты в конечном блоке, чтобы избежать любых утечек. Все, что возвращается из такого метода, НЕ должно быть привязано к какому-либо объекту БД с жизненным циклом и связанными ресурсами.

Тебе не нужно принимать этот совет, но я искренне верю, что твоя жизнь станет легче.

0 голосов
/ 13 декабря 2011

Если вы их уже не пробовали и у них нет нужных вам функций, я не рекомендую использовать JDBC напрямую. Вместо этого просто получите Hibernate, iBatis (вышедший на пенсию, но все еще работающий) или myBatis (следите за iBatis) и позвольте им обрабатывать JDBC. Вероятно, эти инструменты ORM лучше справятся с управлением ресурсами, чем домашний проект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...