带输入参数的命名查询

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 &gt; Java Persistence &gt; JPA &gt; Errors/Warnings &gt; Queries and Generators &gt; 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

【讨论】:

以上是关于带输入参数的命名查询的主要内容,如果未能解决你的问题,请参考以下文章

sql参数查询

带有输入参数的动态sql模糊查询????

带参数的sql查询语句

SQL一个带参数的存储过程写法

8.创建一个存储过程,查询某个学生某门课程的考试成绩(学生名和课程名为输入参数),要求显示姓名,课名和

两个构造函数(带 & 不带参数),无输入 -> 无参数运行。跳过上述类中的构造函数