2.

Hibernate「Number of positional parameter types」の原因と対処

編集
この記事の要点
  • net.sf.hibernate.QueryException: Number of positional parameter types (N) does not match number of positional parameters (M) は、HQL/SQL の ? プレースホルダ数と setParameter() で渡した型/値の数が一致しないときに発生するエラー
  • 原因: ? の数 ≠ setString() / setInteger() 等の呼び出し回数
  • 対処: HQL 中の ? をすべて数えて、index (0 始まり) ごとに setXxx(index, value) を呼ぶ
  • Hibernate 4 以降は positional より named parameter (:name) を推奨。可読性も上がり数え間違いを防げる
  • 関連: SQL 文を logger.debug 等で出力 → ? の数を grep で数えると早い

エラー全文

net.sf.hibernate.QueryException: Number of positional parameter types (1)
  does not match number of positional parameters (2)
  [from User u where u.name = ? and u.deleted = ?]

カッコ内の数字 (1) が型を指定した数、(2) が HQL 中の ? の数。両者が食い違うと発生します。

発生原因

Hibernate の positional parameter? による位置指定パラメータ)を使う場合、HQL/SQL に書いた ? の数と、Java 側で setXxx() を呼ぶ回数は完全一致が必要です。

状況HQL の ?setXxx() 呼出数結果
正常22OK
setXxx を 1 つ忘れた21QueryException
HQL に ? 増やしたが set 忘れ32QueryException
set を余分に呼んだ12QueryException

NG 例 / OK 例

NG: ? 2 個に対し setString 1 個

Query q = session.createQuery(
    "from User u where u.name = ? and u.deleted = ?");
q.setString(0, "alice");
// ↑ deleted の ? が未バインド → QueryException
List<User> users = q.list();

OK: ? 2 個に対し setXxx 2 個

Query q = session.createQuery(
    "from User u where u.name = ? and u.deleted = ?");
q.setString(0, "alice");
q.setBoolean(1, false);
List<User> users = q.list();

推奨: named parameter (:name) に書き換える

positional は数え間違いが起きやすい。名前付きパラメータを使うと安全で可読性も上がります。

// HQL: :name / :deleted を使う
Query q = session.createQuery(
    "from User u where u.name = :name and u.deleted = :deleted");
q.setString("name", "alice");
q.setBoolean("deleted", false);
List<User> users = q.list();

デバッグ手順

  1. 例外メッセージから HQL 全文を確認(スタックトレース末尾)
  2. HQL の ? の数を数える(エディタの検索カウント機能が便利)
  3. Java 側の setXxx() 呼び出しを数える
  4. 不一致箇所を特定 → 追加 or 削除 or named parameter に書き換え
  5. hibernate.show_sql=true で実際に発行された SQL を確認

関連エラー

  • QueryParameterException: could not locate named parameter — 名前付きパラメータの名前が一致しない
  • IllegalArgumentException: Parameter with that position does not exist — JPA でインデックス指定ミス
  • SQLGrammarException — SQL 文法エラー(パラメータ数ではなく文法)
編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. ids for this class must be manually assigned before calling save()
  2. Number of positional parameter types (1 does not match number of positional parameters (2)
  3. net.sf.hibernate.MappingException: No persister for ~
  4. net.sf.hibernate.QueryException: unexpected token: as [~]
  5. net.sf.hibernate.MappingException: Error reading resource
  6. IllegalArgumentException occurred while calling setter of

最近更新/作成されたページ