web-dev-qa-db-ja.com

JPAでプリペアドステートメントを使用する方法

私はPlayFrameworkアプリケーションの開発者です。JPAでcreateNativeQueryメソッドを使用しています。この例では、プリペアドステートメントを使用します。誰か助けてくれませんか?これがJPAなしのコードです。プリペアドステートメントに変換するのに助けが必要です。

Query query = JPA.em().createNativeQuery("select count(*) from truck t inner join" +
    "box b where t.truck_id=b.truck_id and t.shipment_upc='" + code + "'");

BigInteger val = (BigInteger)query.getSingleResult();
System.out.println(val);
9
user3454863
Query query = JPA.em().createNativeQuery("select count(*) from truck t inner join box b where t.truck_id=b.truck_id and t.shipment_upc=:code");
query.setParameter("code", code);
15
Subir Kumar Sao

簡単な要約

ここではクエリパラメータを使用する必要がありますが、ネイティブクエリを使用しているため、JPQLと比較してオプションが制限される場合があります。

世界の状態

あなたは 位置パラメータに限定されます

JPAは、名前付きパラメーターをサポートするネイティブクエリを必要としませんが、一部のJPAプロバイダーは

HibernateによるJPAの実装 名前付きパラメーターをサポート

ネイティブSQLクエリは、位置パラメータと名前付きパラメータをサポートします


解決

Hibernate

Subir Kumar Saoの答え は、名前付きパラメーターを使用してこれを解決する方法を示しています。これは少なくともHibernateでは可能です。

比較のために、ここで繰り返します。

Query query = JPA.em().createNativeQuery(
"SELECT COUNT(*) "+
"FROM truck AS t "+
"INNER JOIN box b "+
"WHERE t.truck_id = b.truck_id "+
"AND t.shipment_upc = :code"
);
query.setParameter("code", code);

ジェネリックJPA(EclipseLinkを含む)

EclipseLink(2.5.1)では、名前付きパラメーターがサポートされていないことがわかりました。

代わりに、位置パラメータを使用する必要があります。これらは、明示的および暗黙的に2つの方法で表現できます。

明示的なインデックス

?1(または他の番号)を使用してパラメーターをマークします。このインデックスを使用して、クエリ内の特定のパラメータを一意に識別できます。

Query query = JPA.em().createNativeQuery(
"SELECT COUNT(*) "+
"FROM truck AS t "+
"INNER JOIN box b "+
"WHERE t.truck_id = b.truck_id "+
"AND t.shipment_upc = ?1"
);
query.setParameter(1, code);

暗黙のインデックス

?だけを使用してパラメータをマークします。そのインデックスは、クエリ文字列に参加しているすべてのパラメータのシーケンスに基づいています。

Query query = JPA.em().createNativeQuery(
"SELECT COUNT(*) "+
"FROM truck AS t "+
"INNER JOIN box b "+
"WHERE t.truck_id = b.truck_id "+
"AND t.shipment_upc = ?"
);
query.setParameter(1, code);

ノート

それを観察してください:

  • 位置パラメータは1インデックスです。
  • Queryパラメータマップのキーは、単に位置パラメータのインデックスです。

追加のソース

5
Birchlabs