Специфика использования JDBC с PostgreSQL
Данный раздел посвящен трем проблемам, часто возникающим при использовании JDBC с PostgreSQL. Первая проблема относительно проста. В объектах ResultSet, возвращаемых в результате вызова executeQuery, указатель текущей записи всегда устанавливается в позицию перед первой записью, возвращенной запросом.
Таким образом, перед выборкой данных из ResultSet необходимо перейти к первой записи методом next. Пример приведен в листинге 12.9. При первом вызове getString возникает исключение, поскольку текущей записи в наборе нет. После вызова next функция getString успешно возвращает значение из первой записи набора.
Листинг 12.9. Выборка данных из первой записи средствами JDBC.
ResultSet newSet = null; try { newSet = s.executeQuery("SELECT * FROM book"): } catch (SQLException se) { System.out.printlnC'We got an exception while executing our query:" + "This probably means that our SQL is invalid."); Специфика использования JDBC с PostgreSQL se.printStackTrace(): System.exit(1): } try { String value = newSet.getString(l); // ПЛОХО: метод next() еще не вызывался } catch (Exception e) { System.out.phntlnC'We'll get an exception here, because we haven't" + " stepped to the first row of the ResultSet yet."); e.printStackTrace(): } try { newSet.next(): String value – newSet.getString(l); } catch (SQLException se) { System.out.printlnC'We'll only get an exception here if we've lost" + "our connection, which isn't our fault."); se.printStackTrace(); System.exit(l); }
Следующая проблема тоже относится к объектам ResultSet, но она значительно проще первой. Вы не можете узнать количество записей, возвращенных в результате запроса, без вызова next с увеличением счетчика. Другими словами, в классе ResultSet не существует простого метода для получения количества записей в наборе. Отчасти это связано с тем, что JDBC может и не получать записи от PostgreSQL (и вообще не знать о существовании таких записей) до вызова next.
Последняя проблема менее очевидна. В многопоточных программах каждый программный поток должен работать с собственными объектами Statement и ResultSet. Дело в том, что в этих объектах хранятся данные состояния, и обращения к ним со стороны других программных потоков могут привести к повреждению этих данных.