2009-11-28 3 views
9

У меня проблема с драйвером JDBC для SQLite.Драйвер JDBC генерирует исключение «ResultSet Closed» на пустом ResultSet

Я выполняю запрос с помощью инструкции SELECT.

Если я получу пустую ResultSet (0 строк), тогда я вижу исключение «Закрытое ResultSet» при вызове getString(1).

Без большого предшествующего опыта JDBC, моя теория (которую я не смог подтвердить с помощью JavaDocs для ResultSet) является то, что

  • getString(1) не работает на пустой (нулевой строки) результирующем (по конструкции или из-за об ошибке)
  • ResultSet «s„открыт“флаг установлен в false на нулевых строк (опять же, по конструкции или ошибка)

Я видел этот bug report, но я не уверен, если это связано ,

Мои мень- шей являются:

  1. Является ли теория выше правильно?
  2. Это ошибка? Особенность? (и если да, может кто-нибудь указать на документацию, пожалуйста?)
  3. Является ли он специфичным для JDBC SQLIte или для общего ResultSet во всех драйверах JDBC?
  4. Каков правильный способ делать такие вещи??

Для # 4, мое решение было использовать isFirst() вызов сразу после executeQuery() проверить, являются ли какие-либо строки есть в наборе результатов. Это лучший подход?

(Я мог бы просто выбрать счетчик вставки, так как мне действительно не нужен набор результатов, просто нулевой ненулевой флаг, но я хочу знать, что нужно делать, если бы я заботился о результатах выбора)

Спасибо!

+1

Спасибо всем! Очень хорошо освещает! – DVK

ответ

17

пустой или нет, но, выполнив следующие действия всегда неисправного:

resultSet = statement.executeQuery(sql); 
string = resultSet.getString(1); // Epic fail. The cursor isn't set yet. 

Это не ошибка. Это documented behaviour. Каждый decent JDBC tutorial упоминает об этом. Вы должны установить курсор ResultSet с помощью next(), прежде чем сможете получить доступ к любым данным.

Если вас действительно интересует, существует ли якобы уникальный номер или нет, то просто проверьте результат next(). Например, в фиктивном UserDAO класса:

public boolean exist(String username, String password) throws SQLException { 
    boolean exist = false; 

    try (
     Connection connection = database.getConnection(); 
     PreparedStatement statement = connection.prepareStatement("SELECT id FROM user WHERE username = ? AND password = MD5(?)"); 
    ) { 
     statement.setString(1, username); 
     statement.setString(2, password); 

     try (ResultSet resultSet = statement.executeQuery()) { 
      exist = resultSet.next(); 
     } 
    } 

    return exist; 
} 

Если вы на самом деле ожидать только ноль или один строку, то просто сделать что-то вроде:

public User find(String username, String password) throws SQLException { 
    User user = null; 

    try (
     Connection connection = database.getConnection(); 
     PreparedStatement statement = connection.prepareStatement("SELECT id, username, email, birthdate FROM user WHERE username = ? AND password = MD5(?)"); 
    ) { 
     statement.setString(1, username); 
     statement.setString(2, password); 

     try (resultSet = statement.executeQuery()) { 
      if (resultSet.next()) { 
       user = new User(
        resultSet.getLong("id"), 
        resultSet.getString("username"), 
        resultSet.getString("email"), 
        resultSet.getDate("birthdate")); 
      } 
     } 
    } 

    return user; 
} 

, а затем просто обработать его соответствующим образом в бизнес/доменный объект, например

User user = userDAO.find(username, password); 

if (user != null) { 
    // Login? 
} 
else { 
    // Show error? 
} 

Если вы на самом деле ожидать только нулевой или много строк, то просто сделать что-то вроде:

public List<User> list() throws SQLException { 
    List<User> users = new ArrayList<User>(); 

    try (
     Connection connection = database.getConnection(); 
     PreparedStatement statement = connection.prepareStatement("SELECT id, username, email, birthdate FROM user"); 
     ResultSet resultSet = statement.executeQuery(); 
    ) { 
     while (resultSet.next()) { 
      users.add(new User(
       resultSet.getLong("id"), 
       resultSet.getString("username"), 
       resultSet.getString("email"), 
       resultSet.getDate("birthdate"))); 
     } 
    } 

    return users; 
} 

, а затем просто обработать его соответствующим образом в объекте бизнес/домена, например,

List<User> users = userDAO.list(); 

if (!users.isEmpty()) { 
    int count = users.size(); 
    // ... 
} 
else { 
    // Help, no users? 
} 
+0

Я выбираю «Принять» это из-за широты примеров кода и ссылки doc. – DVK

6
while (rs.next()) { 
// process the row 
} 
+0

Ответ # 4. Что такое № 1-3? :) – DVK

5

Из JavaDocs для ResultSet:

Объект ResultSet поддерживает курсор , указывающий на его текущей строки данных. Первоначально курсор позиционируется как перед первой строкой. Следующий метод перемещает курсор в следующую строку и , потому что он возвращает false, когда в объекте ResultSet больше нет строк, он может использоваться в цикле while для повторения результатов.

Вам необходимо разместить ResultSet в строке, например. позвонив по телефону next(), прежде чем пытаться прочитать какие-либо данные. Если вызов next() возвращает false, тогда набор результатов пуст.

+0

Ответ # 4. Что такое № 1-3? :) – DVK

+0

@ DVK Не имеет смысла называть 'getString' до тех пор, пока' ResultSet' не будет помещен в строку, поэтому имеет смысл, что он вызывает исключение (это применимо для любого драйвера JDBC). Я не уверен, что вы имеете в виду под «открытым» флагом 'Resultset'. –

+0

В отладчике Eclipse при анализе набора результатов «открытый» член имеет «ложное» значение. Именно по этой причине исключение «ResultSet closed» (не основная причина, но ближайшая переменная, которая рассматривается для генерации исключения в источнике JDBC) – DVK

1

Для такого рода проблемы можно использовать как тот

while(rs.next()) 
{ 
    String name=rs.getString("Name"); 
    int roll_no=Integer.parseInt(rs.getString("Roll")); 
} 
finally 
{ 
    try 
    { 
     rs.close(); 
     pst.close(); 
    } 
    catch(Exception ee) 
    { 
    } 
} 

Joptionpane.showmessahedialog(this,ee); 
+0

Уход за форматированием сообщения. Я отформатировал один из ваших ответов, проверьте это и отформатируйте другие ответы, если они есть! –

+0

thanx Paresh Mayani Я новый для этого сайта. –

+0

Не беспокойтесь ... Продолжайте вносить свой вклад! –