Получение 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
2 ответа
Проблема в том, как вы выбираете данные в 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
Объект одновременно открыт.
Объект ResultSet автоматически закрывается, когда объект Statement, который его сгенерировал, закрывается, выполняется повторно или используется для получения следующего результата из последовательности нескольких результатов.
Я думаю после while(rs2.next())
Вы пытаетесь получить доступ к чему-то из RS1. Но он уже закрыт, так как вы повторно выполнили оператор, чтобы получить от него rs2. Поскольку вы не закрыли его, я полагаю, что он снова используется ниже.