有人可以告诉我,以下JDBC代码中是否需要第一个stmt.close();
,用于针对两个不同的表执行两个不同的SQL查询?
public class MyService {
private Connection connection = null;
public void save(Book book) {
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "password");
PreparedStatement stmt = connection.prepareStatement("INSERT INTO PUBLISHER (CODE, PUBLISHER_NAME) VALUES (?, ?)");
stmt.setString(1, book.getPublisher().getCode());
stmt.setString(2, book.getPublisher().getName());
stmt.executeUpdate();
stmt.close(); //1
stmt = connection.prepareStatement("INSERT INTO BOOK (ISBN, BOOK_NAME, PUBLISHER_CODE) VALUES (?, ?, ?)");
stmt.setString(1, book.getIsbn());
stmt.setString(2, book.getName());
stmt.setString(3, book.getPublisher().getCode());
stmt.executeUpdate();
stmt.close(); //2
} catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }
finally { connection.close(); }
}
}
答案 0 :(得分:10)
在我的书中,我总是建议关闭已经打开的资源以避免可能的泄漏。
稍微更现代的方法是使用try-with-resources:
try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "password")) {
try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO PUBLISHER (CODE, PUBLISHER_NAME) VALUES (?, ?)")) {
stmt.setString(1, book.getPublisher().getCode());
stmt.setString(2, book.getPublisher().getName());
stmt.executeUpdate();
}
// stmt is auto closed here, even if SQLException is thrown
try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO BOOK (ISBN, BOOK_NAME, PUBLISHER_CODE) VALUES (?, ?, ?)");
stmt.setString(1, book.getIsbn());
stmt.setString(2, book.getName());
stmt.setString(3, book.getPublisher().getCode());
stmt.executeUpdate();
}
// stmt is auto closed here, even if SQLException is thrown
}
// connection is auto closed here, even if SQLException is thrown
答案 1 :(得分:4)
这是一个常见的误解,声明关闭它们会释放所有准备它们的东西。这是错的。导致语句准备的优化由数据库执行。然后由数据库存储/缓存它,并且通常在下次准备语句时重复使用。
因此,准备好的陈述可以随时关闭和准备 - 数据库将在下次识别相同的陈述并恢复上次制作的缓存准备 - 如果愿意的话。
总结 - 是,语句应该关闭 - 否,不会降低查询的效率。
答案 2 :(得分:1)
不是必需的,但建议使用。 http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#close()
代码中第一个close()
之后的下一行为引用stmt
分配一个新值,因此用于执行第一个插入的对象将被GC并最终关闭。当你知道自己已经完成它时,最好先关闭它。这会立即释放JDBC资源。
答案 3 :(得分:1)
关闭Statement句柄的好习惯是它将释放JDBC&数据库资源。您可以阅读有关stmt.close()here
的更多信息我想指出,最好在finally块中关闭Statement对象,以便即使发生异常也会释放数据库资源。
答案 4 :(得分:1)
是的,两个stmt.close()方法都是必需的。 您应该始终显式关闭Statement或PreparedStatement对象以确保正确清理。
答案 5 :(得分:1)
try{
String insertIntoCust = "insert into NORTHWIND_CUSTOMER(CUSTOMER_ID,FIRST_NAME,LAST_NAME,ADDRESS,CITY,STATE,POSTAL_CODE) values(?,?,?,?,?,?)";
pst = connect.prepareStatement(insertIntoCust);
pst.setString(1, txtCustomerId.getText());
pst.setString(2, txtFirstName.getText());
pst.setString(3, txtLastName.getText());
pst.setString(4, txtAddress2.getText());
pst.setString(5, txtCity.getText());
pst.setString(6, txtState.getText());
pst.setString(7, txtPostalCode.getText());
pst.execute();
String insertIntoOrder = "insert into NORTHWIND_ORDER(ORDER_ID,ORDER_DATE) values(?,?)";
pst = connect.prepareStatement(insertIntoOrder);
pst.setString(1, txtOrderId.getText());
pst.setString(2, txtOrderDate.getText());
pst.execute();
JOptionPane.showMessageDialog(null, "Saved");
}catch(Exception e){
JOptionPane.showMessageDialog(null, e);
}
使用上面的代码,我可以用一个按钮将数据插入到多个表中。需要在两个查询中插入pst.execute;如果没有,则具有pst.execute的查询是将接收数据的表。