Connection、Statement、PreparedStatement、Resultset注意点メモ
5656 ワード
まずいくつかのテスト結果を記録します.
テスト環境
MySQL:mysql-connector-java-5.1.29.jar
Java:1.7.0_67
テストA
コード:
結果:
結論:
接続が閉じると、関連するResultSetとPreparedStatementが閉じます.
テストB
コード:
結果:
結論:
同じStatementオブジェクトまたはPreparedStatementオブジェクトには、アクティブなResultSetのみが関連付けられます.
テストC
コード:
結果:
結論:
PreparedStatementオブジェクトが閉じずに他のPreparedStatementが関連付けられている場合、古いPreparedStatementとResultSetはConnectionが閉じるまで閉じません.接続プールを使用している場合、メモリが漏洩する可能性があります.
より良い方法:は、Statementの代わりにPreparedStatementを使用する一方で、複数回の実行文の効率を向上させる一方で、SQLの接合による注入攻撃を防止する である. PreparedStatementを閉じることに注意してください.接続プールを使用する場合は特に注意してください.Java 7以上はtry-with-resource文を使用することをお勧めします.簡潔です.Java 7以下ではクローズ時にもtry-catchを注意し、ResultSet、PreparedStatement、Connectionの順にできるだけクローズします. ResultSetを渡さずにRowSetを使用します.
テスト環境
MySQL:mysql-connector-java-5.1.29.jar
Java:1.7.0_67
テストA
コード:
PreparedStatement pstmt = conn
.prepareStatement("select id from world.city limit 3");
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString(1));
}
System.out.println();
PreparedStatement pstmt2 = conn
.prepareStatement("select countrycode from world.city limit 3");
ResultSet rs2 = pstmt2.executeQuery();
while (rs2.next()) {
System.out.println(rs2.getString(1));
}
System.out.println(pstmt.isClosed());
System.out.println(rs.isClosed());
System.out.println(pstmt2.isClosed());
System.out.println(rs2.isClosed());
System.out.println(conn.isClosed());
System.out.println();
conn.close();
System.out.println(pstmt.isClosed());
System.out.println(rs.isClosed());
System.out.println(pstmt2.isClosed());
System.out.println(rs2.isClosed());
System.out.println(conn.isClosed());
System.out.println();
結果:
false
false
false
false
false
true
true
true
true
true
結論:
接続が閉じると、関連するResultSetとPreparedStatementが閉じます.
テストB
コード:
PreparedStatement pstmt = null;
ResultSet rs1 = null;
ResultSet rs2 = null;
Statement st = null;
ResultSet rs3 = null;
ResultSet rs4 = null;
try {
pstmt = conn.prepareStatement(
"select name from world.city where name like ? limit 3");
pstmt.setString(1, "a%");
rs1 = pstmt.executeQuery();
rs2 = null;
while (rs1.next()) {
System.out.println(rs1.getString(1));
pstmt.setString(1, "b%");
rs2 = pstmt.executeQuery();
while (rs2.next()) {
System.out.println(rs2.getString(1));
}
}
}
catch (Exception e) {
e.printStackTrace();
}
try {
st = conn.createStatement();
rs3 = st.executeQuery(
"select name from world.city where name like 'a%' limit 3");
rs4 = null;
while (rs3.next()) {
System.out.println(rs3.getString(1));
rs4 = st.executeQuery(
"select name from world.city where name like 'b%' limit 3");
while (rs4.next()) {
System.out.println(rs4.getString(1));
}
}
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println(pstmt.isClosed());
System.out.println(rs1.isClosed());
System.out.println(rs2.isClosed());
System.out.println(st.isClosed());
System.out.println(rs3.isClosed());
System.out.println(rs4.isClosed());
System.out.println(conn.isClosed());
System.out.println();
結果:
java.sql.SQLException: Operation not allowed after ResultSet closed
java.sql.SQLException: Operation not allowed after ResultSet closed
false
true
false
false
true
false
false
結論:
同じStatementオブジェクトまたはPreparedStatementオブジェクトには、アクティブなResultSetのみが関連付けられます.
テストC
コード:
PreparedStatement pstmt = conn
.prepareStatement("select id from world.city limit 3");
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString(1));
}
System.out.println();
PreparedStatement pstmt_old = pstmt;
pstmt = conn.prepareStatement("select name from world.city where name like ? limit 3");
pstmt.setString(1, "a%");
ResultSet rs2 = pstmt.executeQuery();
while (rs2.next()) {
System.out.println(rs2.getString(1));
}
System.out.println(pstmt.isClosed());
System.out.println(rs.isClosed());
System.out.println(pstmt_old.isClosed());
System.out.println(rs2.isClosed());
System.out.println(conn.isClosed());
System.out.println();
pstmt.close();
System.out.println(pstmt.isClosed());
System.out.println(rs.isClosed());
System.out.println(pstmt_old.isClosed());
System.out.println(rs2.isClosed());
System.out.println(conn.isClosed());
System.out.println();
conn.close();
System.out.println(pstmt.isClosed());
System.out.println(rs.isClosed());
System.out.println(pstmt_old.isClosed());
System.out.println(rs2.isClosed());
System.out.println(conn.isClosed());
System.out.println();
結果:
false
false
false
false
false
true
false
false
true
false
true
true
true
true
true
結論:
PreparedStatementオブジェクトが閉じずに他のPreparedStatementが関連付けられている場合、古いPreparedStatementとResultSetはConnectionが閉じるまで閉じません.接続プールを使用している場合、メモリが漏洩する可能性があります.
より良い方法: