带输入参数的命名查询
Posted
技术标签:
【中文标题】带输入参数的命名查询【英文标题】:Named query with input parameter 【发布时间】:2016-10-21 05:41:51 【问题描述】:我正在使用 Hibernate 学习 JPA,也使用 maven。我的问题是如何在命名查询中使用带有 UPDATE 和 SET 子句的输入参数?
@NamedQuery(name = "updateEmailAddress", query = "Update User u set u.email = :email where u.username = :username")
它给了我一个错误,参数只能在 WHERE 或 HAVING 子句中使用。我参考了几篇文章,但仍然找不到合适的解决方案。
【问题讨论】:
***.com/questions/23103278/… 我提到了它。但还是不能解决问题 在设置前尝试逗号 【参考方案1】:在 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: 使用 HQL 而不是 JPQL 创建查询。我没有对此进行测试,也不推荐它,因为您背着实体经理。
Query q = sessionFactory.getCurrentSession().createNamedQuery('updateEmailAddress');
q.setParameter('email', email);
q.setParameter('username', username);
q.executeUpdate();
【讨论】:
【参考方案2】:虽然实际上在 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
即可
查看this article了解详情:
结论
Hibernate 在这一点上没有遵循规范,而是一个 可能会猜测新版本的 JPA-spec 将允许这样做 JSR 草案所指示的行为。 JBoss 工具可能是 根据 JPQL 语法验证查询,该语法基于 规范,因此显示验证错误。
这是分辨率:
结束备注
经过团队内部的讨论,我们决定保留当前的 尽管违反了规范,但仍能执行。改变 行为将意味着字符串连接或字符串替换 构建查询,当前的方法更干净。正如我们所见,没有 持久性提供程序或应用程序服务器发生变化的迹象 在这个阶段,我们认为保留代码的收益大于 此时的风险。
【讨论】:
【参考方案3】:你可以试试位置参数,看看它是否有效?
@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");
【讨论】:
【参考方案4】:您必须构建一个如下命名的查询:
Query query = getEntityManager().createNamedQuery("updateEmailAddress");
query.setParameter("email", "email@test.com");
query.setParameter("username", "emailuser");
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);
来源:
Hibernate 3.6 - DML-style operations hibernate 4.2 - HQL for UPDATE and DELETE Hibernate Query examples (HQL) Hibernate Query Languages【讨论】:
以上是关于带输入参数的命名查询的主要内容,如果未能解决你的问题,请参考以下文章