如何在JPA命名查询中处理数字类型的空值

时间:2014-10-30 15:09:02

标签: java jpa named-query

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

例如,(id = null,username =' joe')和(id = 1,username =' joe')是两个不同的结果。在namedQuery中,语法为" u.id为null"如果id为null,但是" u.id =:id"如果id不为null。我的问题是如何动态处理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
  2. 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. 从User u中选择你的位置(:id为null或u.id =:id)和u.username =:username

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

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

      //抛出异常:数据类型不一致:预期NUMBER有BINARY

    4. 我也尝试过nvl并在namedQuery中解码,没有用。

    5. query.setParameter(&#34; id&#34;,id == null?-1:id)//没有工作。

    6. 我的最后一个选择是在UserDao文件中编写查询以替换用户文件中的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 ";
                  }
          }
      

3 个答案:

答案 0 :(得分:3)

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

请参阅this回答有关在命名查询中使用的内容。

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

答案 1 :(得分:0)

如果查询结尾处的)出错,请尝试不使用

    @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); 

答案 2 :(得分:0)

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

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

query.setParameter("id", id); 

在命名查询中:

(:idIsSet = false or id = :id)

当id为null时,“ idIsSet”为false。因此,“:idIsSet = false”变为true,并且不会检查ID。