通常のステートメント(java.sql.Statement)を利用することは、エスケープ処理や脆弱性の観点から、あまり良いとは言えません。
また、複数レコードのINSERT等で、何度も同一のSQLを立て続けに発行するような場合、パラメータだけをクリアすることができるため、とくに効果的です。
(ハードパースを抑制することだけでも、データベースは好感度をアップしてくれますw)
こちらを利用するのが普通ですが、もし、通常のステートメントを使用されている方がいれば、即刻、プリペアードステートメントに切り替えることをお勧めします(; ・`д・´)
PreparedStatementでSQLを発行するサンプル
Oracleではお約束のDUAL表より結果を抽出します。
パラメータを渡すため、無駄にDUMMYカラムを条件に含んでみますw
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class PreparedStmtOraTest { public static void main(String[] args) { try { new PreparedStmtOraTest().execute(); }catch(Exception e) { e.printStackTrace(); } } public void execute() throws Exception { //おまじないw(ドライバのロード) Class.forName("oracle.jdbc.driver.OracleDriver"); //DBに接続(URL,USER_ID,PASSWORD) try(Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "scott", "tiger"); PreparedStatement pstmt = conn.prepareStatement("select dummy from dual where dummy = ?")){ //SQLを発行 pstmt.setString(1, "X"); //結果を取得 try(ResultSet rs = pstmt.executeQuery()){ while(rs.next()) { System.out.println("結果:" + rs.getString("dummy")); } } } } } |
実行結果
1 | 結果:X |
サンプルの解説
Statementで発行した場合と比較すると簡単です。
使い方
Connection#prepareStatement(String)にて、コネクションよりプリペアードステートメントを取得する際に、SQLを渡します。発行時は逆に渡しません。
パラメータは、プリペアードステートメントに対して後からセットするため、渡すSQLには、リテラル(値)の代わりに「?」を書いておきます。
パラメータのセットは、?のインデックスに対して、セットします。インデックスは、1始まりで、前から順番になります。
また、パラメータをセットする際に、エスケープ処理は不要です。
性能
SQLの解析は、プリペアードステートメントを取得する時点で行うようになるため、PreparedStatement#executeQuery()にて、実際にSQLを発行した際の性能が改善されます。
場所が変わっただけのように感じられるかもしれませんが、何度でもパラメータを変えて発行できるため、繰り返し発行するような場合には、速度の違いを体感できますw
なお、繰り返すような場合は、以下のような感じで行います。
1 2 3 4 5 6 7 | pstmt = conn.prepareStatement("select dummy from dual where dummy = ?"); for(int i=0 ; i<10 ; i++) { pstmt.clearParameters(); pstmt.setString(1, "X"); rs = pstmt.executeQuery(); //...TODO } |
PreparedStatementでデータを更新するには?
PreparedStatementでデータを更新する方法は、こちらを見てください。