JDBC 実装でよくある落とし穴と SQL テンプレート集

NullPointerException が出る典型的なケース

DAO 層で Connection を取得した直後に Statement を生成しようとした際、conn.createStatement() の呼び出しで NPE が発生することがあります。

Connection conn = DataSourceFactory.getConnection(); // ここで null が返ると…
PreparedStatement ps = conn.prepareStatement(sql);   // ここで例外

原因は DataSourceFactory#getConnection()null を返したことです。コネクション取得メソッドが必ず非 null を返すようにするか、事前にチェックしてください。

頻出 SQL パターン

INSERT

String insert = "INSERT INTO user_account(username, password_hash, role) VALUES (?, ?, ?)";
PreparedStatement ps = conn.prepareStatement(insert);
ps.setString(1, form.getUsername());
ps.setString(2, PasswordUtil.hash(form.getPassword()));
ps.setInt(3, form.getRole());
ps.executeUpdate();

SELECT(部分一致検索)

String fuzzy = "SELECT * FROM student WHERE class_name LIKE ?";
PreparedStatement ps = conn.prepareStatement(fuzzy);
ps.setString(1, "%" + keyword + "%");

SELECT(全件取得)

String all = "SELECT id, name, age FROM tb_qingnian";
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(all);

UPDATE

String update = "UPDATE tb_qingnian SET sex=?, appearance=?, service_type=? WHERE name=?";
PreparedStatement ps = conn.prepareStatement(update);
ps.setString(1, entity.getSex());
ps.setString(2, entity.getAppearance());
ps.setString(3, entity.getServiceType());
ps.setString(4, entity.getName());
ps.executeUpdate();

DELETE

String delete = "DELETE FROM tb_qingnian WHERE name=?";
PreparedStatement ps = conn.prepareStatement(delete);
ps.setString(1, targetName);
ps.executeUpdate();

動的 WHERE 句の組み立て例

JSP でプルダウンで選択された項目を基に検索する場合の実装例です。

JSP

<select name="searchField">
  <option value="category">カテゴリ</option>
  <option value="amount">金額</option>
  <option value="location">場所</option>
  <option value="date">日付</option>
</select>
<input type="text" name="searchValue" />

Servlet

String field = req.getParameter("searchField");
String value = req.getParameter("searchValue");
List<Expense> list = ExpenseDao.findBy(field, value);

DAO

public static List<Expense> findBy(String column, String value) throws SQLException {
    String sql = "SELECT * FROM expense WHERE " + column + " = ?";
    try (Connection conn = DataSourceFactory.getConnection();
         PreparedStatement ps = conn.prepareStatement(sql)) {
        ps.setString(1, value);
        ResultSet rs = ps.executeQuery();
        List<Expense> result = new ArrayList<>();
        while (rs.next()) {
            result.add(new Expense(
                rs.getString("category"),
                rs.getBigDecimal("amount"),
                rs.getString("location"),
                rs.getDate("date")
            ));
        }
        return result;
    }
}

Navicat Premium での「仮想」チェックボックスの注意点

テーブル設計画面で「仮想(Virtual)」にチェックを入れると、MySQL 8 の Generated Column が作成されます。この列は実際にはデータを格納せず、他の列から計算される値のみを保持するため、外部キーやインデックスを設定できないなどの制限が生じます。意図しない仮想列を作らないよう注意してください。

タグ: JDBC PreparedStatement MySQL NullPointerException SQLテンプレート

7月3日 21:03 投稿