2つの異なるテーブルに対して2つの異なるSQLクエリを実行するために、次のJDBCコードで最初のstmt.close();
が必要かどうかを誰かに教えてもらえますか?
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
それらを閉じると、それらを準備するすべてのものが解放されるというステートメントの一般的な誤解です。これは間違っています。ステートメントの準備につながる最適化は、データベースによって実行されます。その後、データベースによって保存/キャッシュされ、通常、次にステートメントが準備されるときに再利用されます。
その結果、準備されたステートメントは、必要に応じて何度でも閉じて準備できます。データベースは、次回同じステートメントを認識し、必要に応じて、前回作成したキャッシュされた準備を回復します。
要約すると、yes、ステートメントを閉じる必要がありますno、これはnotクエリの有効性を低下させます。
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);
}
上記のコードを使用すると、1つのボタンで複数のテーブルにデータを挿入できます。 pst.executeは両方のクエリに挿入する必要があります。そうでない場合、pst.executeを持つクエリは、データを受信するテーブルです。
必須ではありませんが、お勧めします。 http://docs.Oracle.com/javase/7/docs/api/Java/sql/Statement.html#close()
コードの最初のclose()
の後の次の行は、参照stmt
に新しい値を割り当てるため、最初の挿入の実行に使用するオブジェクトはGCされ、最終的に閉じられます。使い終わったことがわかったら、先に進んで閉じることをお勧めします。これにより、JDBCリソースがすぐに解放されます。
JDBCおよびデータベースリソースを解放するため、ステートメントハンドルを閉じることをお勧めします。 stmt.close()についてもっと読むことができます ここ
例外が発生した場合でもDBリソースが解放されるように、finallyブロックでStatementオブジェクトを閉じるとよいことを指摘しておきます。
はい、両方のstmt.close()メソッドが必要です。適切なクリーンアップを確実にするために、StatementまたはPreparedStatementオブジェクトを常に明示的に閉じる必要があります。