Получение java.sql.SQLException: операция не разрешена после закрытия ResultSet
Когда я выполняю следующий код, я получаю исключение. Я думаю, это потому, что я готовлюсь в новом заявлении с тем же объектом соединения. Как мне переписать это, чтобы я мог создать подготовленный оператор и использовать rs2? Должен ли я создавать новый объект соединения, даже если соединение относится к одной и той же БД?
try
{
//Get some stuff
String name = "";
String sql = "SELECT `name` FROM `user` WHERE `id` = " + userId + " LIMIT 1;";
ResultSet rs = statement.executeQuery(sql);
if(rs.next())
{
name = rs.getString("name");
}
String sql2 = "SELECT `id` FROM `profiles` WHERE `id` =" + profId + ";";
ResultSet rs2 = statement.executeQuery(sql2);
String updateSql = "INSERT INTO `blah`............";
PreparedStatement pst = (PreparedStatement)connection.prepareStatement(updateSql);
while(rs2.next())
{
int id = rs2.getInt("id");
int stuff = getStuff(id);
pst.setInt(1, stuff);
pst.addBatch();
}
pst.executeBatch();
}
catch (Exception e)
{
e.printStackTrace();
}
private int getStuff(int id)
{
try
{
String sql = "SELECT ......;";
ResultSet rs = statement.executeQuery(sql);
if(rs.next())
{
return rs.getInt("something");
}
return -1;
}//code continues
Ответы
Ответ 1
Проблема заключается в том, как вы извлекаете данные в getStuff()
. Каждый раз, когда вы посещаете getStuff()
, вы получаете свежий ResultSet
, но вы его не закрываете.
Это нарушает математическое ожидание класса Statement
(см. здесь - http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html):
По умолчанию только один объект ResultSet для объекта Statement может быть открыт одновременно. Поэтому, если чтение одного объекта ResultSet чередуется с чтением другого, каждый из них должен быть сгенерирован различными объектами Statement. Все методы выполнения в интерфейсе Statement неявно закрывают текущий объект ResultSet, если существует открытый.
Что еще хуже, это rs
от вызывающего кода. Он также выводится из поля Statement
, но он не закрыт.
Нижняя строка: у вас есть несколько ResultSet
, относящихся к одному и тому же объекту Statement
, который одновременно открыт.
Ответ 2
Объект ResultSet автоматически закрывается, когда объект Statement, который сгенерированный он закрыт, повторно выполняется, или используется для получения следующего результата из последовательности нескольких результатов.
Я думаю, после while(rs2.next())
вы пытаетесь получить доступ к чему-либо из rs1. Но он уже закрыт, так как вы повторно выполнили выражение, чтобы получить rs2 от него. Поскольку вы не закрыли его, я верю, что он снова используется ниже.