MySQL
 Computer >> コンピューター >  >> プログラミング >> MySQL

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アプリケーションでは、必ずと言っていいほど使われる重要なインターフェースです。

  1. 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 に変更されている点

  2. C#のfinallyステートメントとは?例外処理における役割と使い方を解説

    C#におけるfinallyブロックは、例外がスローされたかどうかにかかわらず、指定した一連のステートメントを必ず実行するために使用します。たとえば、ファイルを開いた場合、処理中に例外が発生してもしなくても、最終的にはファイルを閉じる必要があります。このようなリソースの解放や後始末(クリーンアップ処理)に、finallyブロックが活用されます。エラー処理は、try・catch・finallyという3つのキーワードを組み合わせて実装します。tryブロックには例外が発生する可能性のあるコードを記述し、catchブロックで例外を捕捉して適切に処理し、finallyブロックには例外の有無に関係なく確実に