【问题标题】: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 子句中使用。我参考了几篇文章,但仍然找不到合适的解决方案。

【问题讨论】:

标签: jpa named-query


【解决方案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);
        

        来源:

        【讨论】:

          猜你喜欢
          • 2013-03-11
          • 1970-01-01
          • 2011-01-27
          • 2019-10-15
          • 2017-01-08
          • 1970-01-01
          • 1970-01-01
          • 2020-10-17
          • 1970-01-01
          相关资源
          最近更新 更多