简体   繁体   English

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

[英]PreparedStatement: How to insert data into multiple tables using JDBC

Could somebody tell me whether the first stmt.close(); 有人能告诉我是否第一个stmt.close(); required in the following JDBC code, for executing two different SQL queries against two different tables? 以下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(); }         
    }
}

In my book, I would always recommend closing resources that have been opened to avoid possible leaks. 在我的书中,我总是建议关闭已经打开的资源以避免可能的泄漏。

A slightly more modern way would be to use try-with-resources : 稍微更现代的方法是使用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

It is a common misconception with statements that closing them releases all that preparing them built. 这是一个常见的误解,声明关闭它们会释放所有准备它们的东西。 This is wrong. 这是错的。 The optimisation that results in the preparation of the statement is performed by the database. 导致语句准备的优化由数据库执行。 It is then stored/cached by the database and usually re-used next time the statement is prepared. 然后由数据库存储/缓存它,并且通常在下次准备语句时重新使用。

As a result, prepared statements can be closed and prepared as often as you wish - the database will recognise the same statement next time around and recover the cached preparations it made last time - if it wishes to. 因此,可以根据需要随时关闭和准备准备好的语句 - 数据库将在下次识别相同的语句并恢复上次制作的缓存准备 - 如果愿意的话。

In summary - yes , statements should be closed - and no , this does not reduce the effectiveness of your queries. 总之- 是的 ,声明应被关闭- ,这不会降低您的查询的效率。

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

The next line after the first close() in your code assigns a new value to the reference stmt , so the object you use to execute the first insert will be GC'd and closed eventually. 代码中第一个close()之后的下一行为引用stmt分配一个新值,因此用于执行第一个插入的对象将是GC并最终关闭。 It is good practice to go ahead and close it when you know you're done with it. 当你知道自己已经完成它时,最好先关闭它。 This releases the JDBC resources immediately. 这会立即释放JDBC资源。

Its good practice to close the Statement handle as it will release the JDBC & Database resources. 关闭Statement句柄的好习惯是它将释放JDBC和数据库资源。 You can read more about stmt.close() here 您可以在此处阅读有关stmt.close()的更多信息

I would like to point out that its good to close your Statement object in finally block so that DB resources are released even if an Exception occurs. 我想指出,最好在finally块中关闭Statement对象,以便即使发生异常也会释放数据库资源。

Yes, both the stmt.close() methods are necessary. 是的,两个stmt.close()方法都是必需的。 You should always explicitly close the Statement or PreparedStatement object to ensure proper cleanup. 您应该始终显式关闭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);
 }

With the code above, I could insert data into multiple tables with one button. 使用上面的代码,我可以使用一个按钮将数据插入到多个表中。 The pst.execute need to be inserted in both queries; 需要在两个查询中插入pst.execute; if not, the query that have the pst.execute is the table that will receive the data. 如果没有,则具有pst.execute的查询是将接收数据的表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM