JDBCのPreparedStatementとは?使い方をサンプルコード付きで解説
PreparedStatementインターフェースは、Statementインターフェースを継承したものであり、複数回実行できる「事前コンパイル済みのSQL文」を表します。パラメータ化されたSQLクエリを受け付けることができ、0個以上のパラメータを渡せます。
まずSQL文では、パラメータの代わりにプレースホルダー「?」を記述しておき、後からPreparedStatementインターフェースが提供するsetXXX()メソッドを使って、動的に値を渡すことができます。
PreparedStatementのメリット
PreparedStatementを使う主なメリットは次のとおりです。
SQLインジェクション対策: パラメータがSQL文に直接文字列として結合されないため、悪意のある入力によるSQLインジェクションを防げます。
パフォーマンスの向上: SQL文が一度コンパイル(プリコンパイル)されるため、同じ文を繰り返し実行する場合に高速に処理できます。
可読性・保守性の向上: 値がプレースホルダーとして分離されるため、SQL文が読みやすくなり、修正も容易になります。
PreparedStatementの作成方法
PreparedStatementオブジェクトは、ConnectionインターフェースのprepareStatement()メソッドを使って作成します。このメソッドはパラメータ化されたSQLクエリを引数に受け取り、PreparedStatementオブジェクトを返します。
このメソッドを呼び出すと、Connectionオブジェクトは指定されたクエリをデータベースへ送信し、コンパイルして保存します。クエリのコンパイルが成功した場合にのみ、オブジェクトが返されます。
コンパイルの時点では具体的な値は不要なため、SQL文中の値の部分には(0個以上の)プレースホルダー(疑問符「?」)を置くことができます。
たとえば、データベースに次のSQLで作成されたEmployeeテーブルがあるとします。
CREATE TABLE Employee(Name VARCHAR(255), Salary INT NOT NULL, Location VARCHAR(255));
このテーブルに値を挿入する場合は、次のようにPreparedStatementを利用できます。
// PreparedStatementの作成 String query = "INSERT INTO Employee(Name, Salary, Location) VALUES(?, ?, ?)"; PreparedStatement pstmt = con.prepareStatement(query);
プレースホルダーへの値の設定
PreparedStatementインターフェースには、setInt()、setFloat()、setArray()、setDate()、setDouble()など、プレースホルダーに値を設定するためのsetterメソッドが多数用意されています。
これらのメソッドは2つの引数を受け取ります。第1引数はプレースホルダーの位置を示すインデックス(整数値)、第2引数はその位置に設定する値(int、String、floatなど)です。なお、インデックスは1から始まる点に注意してください。
先ほど作成したステートメントのプレースホルダーには、次のようにsetterメソッドで値を設定できます。
pstmt.setString(1, "Amit"); pstmt.setInt(2, 3000); pstmt.setString(3, "Hyderabad");
PreparedStatementの実行
PreparedStatementオブジェクトを作成したら、同インターフェースが提供するexecute系メソッド、すなわちexecute()、executeQuery()、executeUpdate()のいずれかを使って実行します。
execute(): 現在のPreparedStatementオブジェクトのSQL文を実行し、boolean値を返します。
executeQuery(): 現在のPreparedStatementを実行し、検索結果を格納したResultSetオブジェクトを返します。
executeUpdate(): INSERT、UPDATE、DELETEなどのSQL DML文を実行し、影響を受けた行数を表す整数値を返します。
サンプルプログラム
それでは、PreparedStatementを使ってEmployeesテーブルに複数のレコードを挿入する例を見てみましょう。値を設定するたびにexecuteUpdate()を呼び出すことで、同じSQL文を再利用しながら複数行を挿入できます。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class PreparedStatementExample {
public static void main(String args[]) throws SQLException {
// ドライバの登録
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
// データベースへの接続
String mysqlUrl = "jdbc:mysql://localhost/testdb";
Connection con = DriverManager.getConnection(mysqlUrl, "root", "password");
System.out.println("接続が確立されました......");
// PreparedStatementの作成
String query = "INSERT INTO Employees(Name, Salary, Location) VALUES (?, ?, ?)";
PreparedStatement pstmt = con.prepareStatement(query);
// 1件目のデータを設定して実行
pstmt.setString(1, "Amit");
pstmt.setInt(2, 3000);
pstmt.setString(3, "Hyderabad");
pstmt.executeUpdate();
// 2件目のデータを設定して実行
pstmt.setString(1, "Kalyan");
pstmt.setInt(2, 4000);
pstmt.setString(3, "Vishakhapatnam");
pstmt.executeUpdate();
// 3件目のデータを設定して実行
pstmt.setString(1, "Renuka");
pstmt.setInt(2, 5000);
pstmt.setString(3, "Delhi");
pstmt.executeUpdate();
// 4件目のデータを設定して実行
pstmt.setString(1, "Archana");
pstmt.setInt(2, 15000);
pstmt.setString(3, "Mumbai");
pstmt.executeUpdate();
System.out.println("レコードを挿入しました......");
}
}実行結果
接続が確立されました...... レコードを挿入しました......
データベースを確認すると、テーブルに次のように値が挿入されていることがわかります。
+---------+--------+----------------+ | Name | Salary | Location | +---------+--------+----------------+ | Amit | 3000 | Hyderabad | | Kalyan | 4000 | Vishakhapatnam | | Renuka | 5000 | Delhi | | Archana | 15000 | Mumbai | +---------+--------+----------------+ 4 rows in set (0.00 sec)
このようにPreparedStatementを活用することで、同一のSQL文を再利用しながら、異なる値を安全かつ効率的にデータベースへ挿入できます。特に同じ処理を繰り返し実行するバッチ処理やWebアプリケーションでは、必ずと言っていいほど使われる重要なインターフェースです。
-
MySQL JDBCドライバーの接続文字列とは?書き方と使い方を解説
MySQL JDBCドライバーの接続文字列とはJavaからMySQLデータベースへ接続する際に必要となるのが「JDBC接続文字列」です。まず、MySQLのJDBCドライバーを読み込むためのコードは以下のようになります。Class.forName(com.mysql.jdbc.Driver);ここで指定している Driver はインターフェースであり、このクラスをロードすることでMySQL用のJDBCドライバーが利用可能になります。なお、新しいMySQL Connector/J(バージョン8.0以降)では、ドライバークラス名が com.mysql.cj.jdbc.Driver に変更されている点
-
C#のfinallyステートメントとは?例外処理における役割と使い方を解説
C#におけるfinallyブロックは、例外がスローされたかどうかにかかわらず、指定した一連のステートメントを必ず実行するために使用します。たとえば、ファイルを開いた場合、処理中に例外が発生してもしなくても、最終的にはファイルを閉じる必要があります。このようなリソースの解放や後始末(クリーンアップ処理)に、finallyブロックが活用されます。エラー処理は、try・catch・finallyという3つのキーワードを組み合わせて実装します。tryブロックには例外が発生する可能性のあるコードを記述し、catchブロックで例外を捕捉して適切に処理し、finallyブロックには例外の有無に関係なく確実に