PreparedStatement:如何使用JDBC将数据插入多个表

有人能告诉我是否第一个stmt.close(); 以下JDBC代码中是否需要针对两个不同的表执行两个不同的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(); } } } 

在我的书中,我总是建议关闭已经打开的资源以避免可能的泄漏。

稍微更现代的方法是使用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 

这是一个常见的误解,声明关闭它们会释放所有准备它们的东西。 这是错的。 导致语句准备的优化由数据库执行。 然后由数据库存储/缓存它,并且通常在下次准备语句时重新使用。

因此,可以根据需要随时关闭和准备准备好的语句 – 数据库将在下次识别相同的语句并恢复上次制作的缓存准备 – 如果愿意的话。

总而言之 – 是的 ,语句应该被关闭 – ,这不会降低查询的有效性。

这不是必需的,但建议使用。 http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#close()

代码中第一个close()之后的下一行为引用stmt分配一个新值,因此用于执行第一个插入的对象将是GC并最终关闭。 当你知道自己已经完成它时,最好先关闭它。 这会立即释放JDBC资源。

关闭Statement句柄的好习惯是它将释放JDBC和数据库资源。 您可以在此处阅读有关stmt.close()的更多信息

我想指出,最好在finally块中关闭Statement对象,以便即使发生exception也会释放数据库资源。

是的,两个stmt.close()方法都是必需的。 您应该始终显式关闭Statement或PreparedStatement对象以确保正确清理。

  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的查询是将接收数据的表。