私はHibernateでJPAを学び、Mavenも使用しています。私の問題は、名前付きクエリのUPDATEおよびSET句で入力パラメーターを使用するにはどうすればよいですか?
@NamedQuery(name = "updateEmailAddress", query = "Update User u set u.email = :email where u.username = :username")
パラメータがWHEREまたはHAVING句でのみ使用できるというエラーが表示されます。いくつかの記事を参照しましたが、適切な解決策が見つかりません。
JPA 2.0以下では、名前付きクエリのset句でパラメーターを使用できません。リテラルのみ。 JPA 2.1を使用している場合、この制限は解除されます。
私が収集できるものから、あなたはJPA 2.1を使用していません。したがって、この制限を回避する方法をいくつか紹介します。
オプション1:createQueryメソッドを使用して、動的に生成された文字列をメソッドに渡します。
String queryString = generateQueryString(email, username);
entityManager.createQuery(queryString).executeUpdate();
オプション2:関連するエンティティを更新してマージします。
List<User> result = entityManager.createQuery('select u from user u where
u.username = :username').setParameter('username', username).getResultList();
for (User user : result) {
user.setEmail(email);
entityManager.merge(user);
}
オプション3:JPQLではなくHQLを使用してクエリを作成します。あなたはエンティティマネージャーの後ろを向いているので、私はこれをテストしていませんし、お勧めしません。
Query q = sessionFactory.getCurrentSession().createNamedQuery('updateEmailAddress');
q.setParameter('email', email);
q.setParameter('username', username);
q.executeUpdate();
実際にはJPA 2.1まではこれが許可されていませんでしたが、プロバイダーはそのようにパラメーターを提供できるため、実際に使用できます(これは良いことです)。
JPAプロバイダーはこの検証に関する仕様に準拠していないようですが、それは意味がないためだと思います(2.1で確認できるようになりました)。 「なぜ開発者を難しくするのですか?」
私はEclipseLink 2.3.1も使用していますが、問題なく動作しています。
EclipseのJPQLクエリ検証を無効にするだけです。
プロバイダーがそれを受け入れる場合は問題ありません。そうでない場合は、仕様に準拠する必要があります。とても簡単です。コードはよりクリーンになり、仕様の最近の評価に準拠します。
ちょうど行く:Preferences > Java Persistence > JPA > Errors/Warnings > Queries and Generators > Invalid or incomplete JPQL queries:
およびIgnore
それ
詳細は この記事 を確認してください:
結論
Hibernateはこの点で仕様に準拠していませんが、新しいバージョンのJPA-specでは、ドラフトJSRで示されているように、この動作が許可されていると推測できます。 JBoss Toolsはおそらく仕様に基づくJPQL-grammarに対してクエリを検証しているため、検証エラーが表示されています。
そしてこれが解決策です:
最後のコメント
外のチームで話し合った後、仕様に違反しても現在の実装を維持することにしました。動作を変更することは、クエリを構築するための文字列連結または文字列置換を意味し、現在のアプローチははるかにクリーンです。この段階で永続性プロバイダーまたはアプリケーションサーバーの変化の兆候は見られないので、コードを維持することによる利益は、現時点でのリスクよりも大きいと考えています。
次のような名前のクエリを作成する必要があります。
Query query = getEntityManager().createNamedQuery("updateEmailAddress");
query.setParameter("email", "[email protected]");
query.setParameter("username", "emailuser");
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);
出典:
位置パラメータを試して、それが機能するかどうかを確認できますか?
@NamedQuery(name = "updateEmailAddress", query = "UPDATE User u SET u.email = ?1 WHERE u.username = ?2")
//The parameter needs to be passed as
query.setParameter(1, "the_emailaddress");
query.setParameter(2, "the_username");