カテゴリ: JavaのJDBC 更新日: 2026/05/07

JavaのJDBCでPreparedStatementを使ってSQLインジェクションを防ぐ方法を徹底解説

2100
JDBC の PreparedStatement を使って SQL インジェクションを防ぐ

先生と生徒の会話形式で理解しよう

生徒

「JavaのJDBCでデータベースにアクセスするとき、SQLインジェクションって何ですか?」

先生

「SQLインジェクションは、不正なSQL文を入力されることで、データベースの情報が盗まれたり改ざんされたりするセキュリティ攻撃です。」

生徒

「それは怖いですね。Javaではどうやって防ぐんですか?」

先生

「JDBCのPreparedStatementを使うことで、安全にSQLを実行できます。具体的な書き方を見ていきましょう。」

1. JDBCとSQLインジェクションとは

1. JDBCとSQLインジェクションとは
1. JDBCとSQLインジェクションとは

Javaでデータベースに接続するための標準APIがJDBCです。JDBCを使うことで、MySQLやPostgreSQLなどのデータベースと連携できます。しかし、SQL文を文字列として組み立てる方法では、SQLインジェクションという深刻なセキュリティ問題が発生する可能性があります。

SQLインジェクションとは、ログインフォームや検索フォームなどの入力欄に悪意あるSQLコードを入力されることで、本来意図しないデータ取得や削除が実行される攻撃です。Java初心者でも必ず理解しておくべき重要なセキュリティ対策の一つです。

2. Statementを使った危険な書き方

2. Statementを使った危険な書き方
2. Statementを使った危険な書き方

まずは危険な例を確認しましょう。Statementで文字列連結してSQLを作る方法です。


import java.sql.*;

public class LoginSample {
    public static void main(String[] args) throws Exception {
        String userId = "admin";
        String password = "1234";

        Connection conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/sampledb", "root", "pass");

        Statement stmt = conn.createStatement();
        String sql = "SELECT * FROM users WHERE user_id = '" 
                   + userId + "' AND password = '" + password + "'";

        ResultSet rs = stmt.executeQuery(sql);

        while (rs.next()) {
            System.out.println("ログイン成功");
        }

        conn.close();
    }
}

この方法では、入力値に「' OR '1'='1」のような文字列を入れられると、認証を回避される可能性があります。これがSQLインジェクションの代表例です。

3. PreparedStatementとは何か

3. PreparedStatementとは何か
3. PreparedStatementとは何か

PreparedStatementは、SQL文のひな型を事前に用意し、後から値を安全にセットできる仕組みです。値の部分はプレースホルダである疑問符を使います。

PreparedStatementを使うことで、入力値はSQL文として解釈されず、単なるデータとして扱われます。そのため、SQLインジェクション対策として非常に有効です。JavaのWebアプリ開発や業務システム開発では必須の知識です。

Javaをこれから始める人や、 オブジェクト指向の考え方を基礎から理解したい人には、 定番の入門書がこちらです。

スッキリわかるJava入門 第4版をAmazonで見る

※ Amazon広告リンク

4. PreparedStatementを使った安全な書き方

4. PreparedStatementを使った安全な書き方
4. PreparedStatementを使った安全な書き方

それでは安全なコード例を見てみましょう。


import java.sql.*;

public class SecureLoginSample {
    public static void main(String[] args) throws Exception {
        String userId = "admin";
        String password = "1234";

        Connection conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/sampledb", "root", "pass");

        String sql = "SELECT * FROM users WHERE user_id = ? AND password = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);

        pstmt.setString(1, userId);
        pstmt.setString(2, password);

        ResultSet rs = pstmt.executeQuery();

        while (rs.next()) {
            System.out.println("ログイン成功");
        }

        conn.close();
    }
}

疑問符の部分にsetStringメソッドで値をセットしています。この方法なら、悪意ある文字列が入力されてもSQL構造は壊れません。これがJDBC PreparedStatementによるSQLインジェクション防止の基本です。

5. 数値や更新処理での使い方

5. 数値や更新処理での使い方
5. 数値や更新処理での使い方

PreparedStatementはSELECT文だけでなく、INSERTやUPDATEでも使えます。


import java.sql.*;

public class InsertSample {
    public static void main(String[] args) throws Exception {
        Connection conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/sampledb", "root", "pass");

        String sql = "INSERT INTO users (user_id, age) VALUES (?, ?)";
        PreparedStatement pstmt = conn.prepareStatement(sql);

        pstmt.setString(1, "tanaka");
        pstmt.setInt(2, 25);

        int result = pstmt.executeUpdate();
        System.out.println(result + "件登録しました");

        conn.close();
    }
}

1件登録しました

setIntのようにデータ型に合わせて値を設定できる点も特徴です。これにより型安全なデータベース操作が可能になります。

6. LIKE検索とPreparedStatement

6. LIKE検索とPreparedStatement
6. LIKE検索とPreparedStatement

あいまい検索を行う場合もPreparedStatementは有効です。


import java.sql.*;

public class LikeSearchSample {
    public static void main(String[] args) throws Exception {
        Connection conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/sampledb", "root", "pass");

        String keyword = "ta";
        String sql = "SELECT * FROM users WHERE user_id LIKE ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);

        pstmt.setString(1, "%" + keyword + "%");

        ResultSet rs = pstmt.executeQuery();

        while (rs.next()) {
            System.out.println(rs.getString("user_id"));
        }

        conn.close();
    }
}

LIKE検索でも文字列連結はJava側で行い、SQL文自体は固定することがポイントです。これによりセキュアな検索機能を実装できます。

7. PreparedStatementを使うメリットまとめ

7. PreparedStatementを使うメリットまとめ
7. PreparedStatementを使うメリットまとめ

PreparedStatementを使うことで、SQLインジェクション対策ができるだけでなく、パフォーマンス向上にもつながります。SQL文を事前にコンパイルするため、同じSQLを繰り返し実行する場合に効率的です。

Java JDBC開発では、StatementではなくPreparedStatementを使うことがベストプラクティスです。特にWebアプリケーションや業務システムでは、セキュリティ対策として必須です。初心者の段階から正しい書き方を身につけておくことで、安全なJavaプログラミングが実現できます。

まとめ

まとめ
まとめ

今回はJavaのJDBCを使ったデータベース接続において、SQLインジェクションをどのように防ぐかを具体的なコード例とともに詳しく確認しました。Java初心者の方にとっては、JDBCやPreparedStatementという言葉自体が難しく感じられるかもしれません。しかし、Webアプリ開発や業務システム開発において、データベース操作とセキュリティ対策は避けて通れない重要な知識です。

まず理解しておくべきポイントは、StatementでSQL文を文字列連結して組み立てる方法は非常に危険だということです。ユーザー入力をそのままSQLに埋め込むと、不正なSQL文を実行される可能性があり、これがSQLインジェクション攻撃の原因になります。ログイン機能や検索機能、会員登録機能など、入力フォームを持つJavaアプリケーションでは常にリスクが存在します。

それに対してPreparedStatementは、SQL文の構造と値を分離して扱う仕組みです。疑問符によるプレースホルダを使用し、setStringやsetIntなどのメソッドで値を後から安全に設定します。この仕組みによって、入力値は単なるデータとして処理され、SQL構造が壊れることはありません。これがJDBC PreparedStatementによるSQLインジェクション対策の基本原理です。

さらに、PreparedStatementはSELECT文だけでなく、INSERT文、UPDATE文、DELETE文といった更新処理にも利用できます。型に応じたメソッドで値を設定できるため、型安全なデータベース操作が実現できます。これはバグの防止にもつながり、結果的に保守性の高いJavaプログラムになります。

また、LIKE検索のようなあいまい検索においても、SQL文自体は固定し、ワイルドカードをJava側で組み立ててからsetStringで渡すことが重要です。SQLを動的に連結するのではなく、必ずプレースホルダを利用するという習慣を身につけましょう。

パフォーマンス面でもPreparedStatementは有利です。同じSQLを繰り返し実行する場合、事前にコンパイルされたSQLが利用されるため、処理効率が向上します。セキュリティ対策と性能向上を同時に実現できる点は、Java JDBC開発における大きなメリットです。

これからJavaでWebアプリケーションを開発する方、Springなどのフレームワークを学習する方、業務システムでデータベース連携を行う方は、必ずPreparedStatementを基本として覚えてください。安全なコーディングを最初から習慣化することが、強固なシステム構築への第一歩です。

サンプルプログラムで最終確認


import java.sql.*;

public class PreparedStatementReviewSample {
    public static void main(String[] args) throws Exception {

        String userId = "suzuki";
        int age = 30;

        Connection conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/sampledb", "root", "pass");

        String insertSql = "INSERT INTO users (user_id, age) VALUES (?, ?)";
        PreparedStatement insertStmt = conn.prepareStatement(insertSql);
        insertStmt.setString(1, userId);
        insertStmt.setInt(2, age);
        insertStmt.executeUpdate();

        String selectSql = "SELECT user_id, age FROM users WHERE user_id = ?";
        PreparedStatement selectStmt = conn.prepareStatement(selectSql);
        selectStmt.setString(1, userId);

        ResultSet rs = selectStmt.executeQuery();

        while (rs.next()) {
            System.out.println(rs.getString("user_id") + " : " 
                + rs.getInt("age"));
        }

        conn.close();
    }
}

suzuki : 30

このように、SQL文は固定し、値だけを安全に設定することが最も重要です。Java JDBCでのデータベース接続、SQL実行、セキュリティ対策、パフォーマンス改善という観点からも、PreparedStatementは標準的な実装方法です。今後Javaでデータベースを扱うときは、必ずPreparedStatementを利用するという意識を持ち続けてください。

先生と生徒の振り返り会話

生徒

JavaのJDBCでSQLを実行するときは、文字列連結ではなくPreparedStatementを使うことが大切だと理解できました。

先生

その通りです。SQLインジェクション対策は、Javaプログラミングにおける基本的なセキュリティ知識です。

生徒

疑問符でプレースホルダを用意して、setStringやsetIntで値を設定すれば安全になるのですね。

先生

はい。SQL文の構造とデータを分離することが重要です。これによりデータベースの安全性が高まります。

生徒

SELECTだけでなくINSERTやUPDATEでも同じ考え方を使える点も理解できました。

先生

素晴らしい理解です。これからJavaでWebアプリや業務システムを作るときも、必ずPreparedStatementを基本にしてください。

生徒

はい。安全なデータベース操作を意識して、SQLインジェクションを防げるエンジニアを目指します。

JavaのJDBCの一覧へ
新着記事
AWS
【AWS】CLIを使った自動化・シェルスクリプト活用術
AWS CLIを使った自動化とシェルスクリプト活用術を徹底解説 初心者でもできるクラウド運用効率化
Flutter
RiverpodとProviderの違いを比較!どちらを使う?
FlutterのRiverpodとProviderの違いを比較解説!初心者向けの使い分けガイド
AWS
【AWS】S3のストレージクラスの違いとは?標準・IA・Glacierの選び方
【AWS】S3のストレージクラスの違いとは?標準・IA・Glacierの選び方を初心者向けに解説
AWS
【AWS】S3バケットの作成方法と命名ルールまとめ
【AWS】S3バケットの作成方法と命名ルールまとめ!初心者向け手順解説
人気記事
Java
Java の getter メソッドと setter メソッドの使い方
Javaのgetterメソッドとsetterメソッドの使い方を完全ガイド!初心者でもわかるアクセス方法
Java
Java の Random クラスを使ってランダムな数値を生成する方法
JavaのRandomクラスの使い方を完全ガイド!初心者でもわかる乱数生成
AWS
【AWS】RDSの料金体系まとめ!ざっくり理解・高いと感じる理由も解説
【AWS】RDSの料金体系まとめ!ざっくり理解・高いと感じる理由も解説
AWS
【AWS】s3 cpコマンド完全ガイド!基本・recursive・exclude/includeも解説
【AWS】s3 cpコマンド完全ガイド!基本・recursive・exclude/includeも解説

🔌 USBポート不足を解消

Type-C 1本で拡張。
開発・作業環境を一気に快適に

UGREEN USB-Cハブを見る

※ Amazon広告リンク