【问题标题】:How to handle null value of number type in JPA named query如何在 JPA 命名查询中处理数字类型的空值
【发布时间】:2014-12-26 17:00:31
【问题描述】:

我想将两个参数传递给命名查询。一种是数字类型,另一种是字符串类型。它们都可以为空。

例如,(id=null, username='joe') 和 (id=1, username='joe') 是两个不同的结果。在 namedQuery 中,如果 id 为 null,则语法为“u.id is null”,如果 id 不为 null,则语法为“u.id = :id”。我的问题是如何动态处理namedQuery中归档的id?

请查看我的示例代码:

1.User.java

@NamedQueries({
        @NamedQuery(name = "getUser", query = "select u from User u"
                + " where u.id = :id"    
                + " And u.username= :username")
})
public class User{
     public Long id;
     public String username;
}
  1. UserDao.java
public User getUser(Long id, String username) {
    TypedQuery<User> query = Dao.entityManager.createNamedQuery("getUser", User.class);
    query.setParameter("id", id);
    query.setParameter("username", username);

    List<User> users = query.getResultList();

    if (users.size() > 0) {
        return users.get(0);
    } else {
        return null;
    }
}

========================================

我尝试过的:

  1. 这是遗留代码,我不想更改结构。所以我不想使用 Criteria。

  2. 从用户 u 中选择 u,其中 (:id 为 null 或 u.id= :id) 和 u.username= :username

    // 抛出异常:不一致的数据类型:预期的 NUMBER 得到了 BINARY

  3. 从用户 u 中选择 u 其中 u.id= nullif(:id, null) 和 u.username= :username

    // 抛出异常:不一致的数据类型:预期的 NUMBER 得到了 BINARY

  4. 我也试过nvl和namedQuery中的decode,没用。

  5. query.setParameter("id", id==null?-1:id) // 没用。

我最后的选择是在 UserDao 文件中编写查询来替换 User 文件中的 namedQuery。

谢谢!

=============================================

我的时间不多了,不得不放弃使用 namedQuery。我的解决方案:

# UserDao.java 

  public User getUser(Long id, String usename) {
        String getUser = "select u from user u where u.id " + Dao.isNull(id) 
                       + " And u.username " + Dao.isNull(username);
        Query query = Dao.entityManager.createQuery(getUser);
    }

# Dao.java

   public static String isNull(Object field) {
        if (field != null) {
                if (field instanceof String) {
                    return " = " + "'" + field + "'";
                } else {
                    return " = " + field;
                }

            } else {
                return " is NULL ";
            }
    }

【问题讨论】:

  • 您确定问题出在参数上吗?除了这个 null 问题之外,查询还能正常工作并返回正确的结果?
  • oracle 不将空字符串视为 Null 吗?
  • 是的。这是空问题。该代码之前运行良好。我刚刚遇到了这个问题,因为我们想更改 id 字段可以为空的要求。以前,id 字段是非空的。
  • 那个 id 字段是主键吗?为什么需要一个接受空值的主键字段?对我来说听起来不对!
  • 如果它是唯一的主键,那么该查询的第二部分就无关紧要了。

标签: java jpa named-query


【解决方案1】:

如果查询末尾的 ) 有误,请尝试不使用它

    @NamedQuery(name = "getUser", query = "select u from User u"
            + " where (:id is null or u.id = :id)"    
            + " And :username"

编辑

如果一切都失败了,这个快速的解决方法应该结合上面的空检查来做(如果你在数据库中没有负 ID)

query.setParameter("id", id == null ? -1 : id); 

【讨论】:

  • 感谢您的指正。那是我的错字。该方法无效。
  • 这是一个查询,而不是 java 语句。 :id is null 在查询世界中毫无意义,因为:id 是传递的变量,数据库未知。
  • @pmp 这不是没有意义,它是故意使用变量的。像这样的表达式的要点是,如果您将null 作为参数值传递,OR 的左侧将被评估为true,因此根本不会考虑右侧。
  • @Bryan This 的帖子提出了类似WHERE :id is null OR u.id = COALESCE(:id, -1) 的解决方法,值得一试。
  • @PredragMaric 你能告诉我任何解释这个“OR”运算符的教程吗?谢谢!
【解决方案2】:

您不能在运行时更改命名查询。这样做会破坏命名查询的目的。 应使用条件 api 创建动态查询。

请参阅this 回答,了解在命名查询中使用什么。

   from CountryDTO c where 
    ((:status is null and c.status is null) or c.status = :status) 
    and c.type =:type

【讨论】:

  • 试过了。抛出异常:ORA-00932:不一致的数据类型:预期的 NUMBER 得到了 BINARY
【解决方案3】:

尝试让布尔值检查空值。它对我有用。

query.setParameter("idIsSet", id != null); 

query.setParameter("id", id); 

在命名查询中:

(:idIsSet = false or id = :id)

当 id 为空时,“idIsSet”为假。所以 ":idIsSet = false" 变成了 true 就不会检查 id 了。

【讨论】:

    猜你喜欢
    • 2014-11-03
    • 2011-08-16
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-31
    相关资源
    最近更新 更多