条件查询左外连接未返回正确的值

时间:2015-10-22 03:18:21

标签: java jpa join predicate criteria-api

我有两张表有很多对很多的关系。 1表是用户,第二个表是组。这意味着1个用户可以拥有多个组。而1组可以有很多用户。这是我桌子的内容:

      Table User                              Table Group
+------------------------------+      +-----------------------------+
| Name   | Age |  Group        |      | Name     | User             |
+------------------------------+      +-----------------------------+
|Fikrie  | 21  |  Unix         |      | Unix     | Fikrie, Fikrie1  |
|Fikrie1 | 22  |  Windows      |      | Windows  | Fikrie1,Fikrie2  |
|Fikrie2 | 23  |  Unix,Windows |      | HP-UX    |                  |
|Lucy    | 21  |               |      +-----------------------------+
|Lucy1   | 22  |               |
+------------------------------+

每当我尝试查询时,我只设法让拥有组的用户。对于可能的情况,我只能设法得到所有的Fikries。为什么我的查询缺少Lucys?这是我的代码:

public List<User> retrieveAll(String nameFilter, String groupFilter, int start, int length) {

    logger.info("nameFilter = [" + nameFilter + "]");
    logger.info("groupFilter = [" + groupFilter + "]");
    logger.info("start is = [" + start + "]");
    logger.info("length is = [" + length + "]");

    ServiceUtil.requireAdmin();
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<User> q = cb.createQuery(User.class);
    Root<User> c = q.from(User.class);
    Join<User, UserGroup> usrGrp = c.join(
            User_.userGroups, JoinType.LEFT);

    q.select(c);

    Predicate namePredicate = cb.like(c.get(User_.name), "%"
            + nameFilter.toLowerCase() + "%");        
    Predicate groupPredicate = cb.like(usrGrp.get(UserGroup_.name),
            "%" + groupFilter.toLowerCase() + "%");        
    Predicate andPredicate = cb.and(namePredicate, groupPredicate);
    q.where(andPredicate);

    List<User> results = em.createQuery(q).setFirstResult(start)
            .setMaxResults(length).getResultList();
    int i = 0;
    for (User usr : results) {
        logger.info("Name=" + usr.getName());
        for (UsrGroup usrgroup2 : usr.getUserGroups()) {
            logger.info("usrgroups = [" + usrgroup2.getName() + "]");
        }
    }
    return results;
}

这是运行查询后的日志:

nameFilter = []
groupFilter = []
start is = [0]
length is = [5]
Name=Fikrie
usrgroups = [Unix]
Name=Fikrie1
usrgroups= [Windows]
Name=Fikrie2
usrgroups= [Unix]
usrgroups= [Windows]

this文档中,它表示使用Left类型的连接来应用左外连接。为什么它仍然缺少没有任何组的其他2个用户?根据我的理解,通过引用here,左外连接应该可以解决问题。

我尝试了什么:

删除groupPredicate,只需按名称进行过滤。然后我得到所有用户。

记录结果:

nameFilter = []
groupFilter = []
start is = [0]
length is = [5]
Name=Fikrie
usrgroups = [Unix]
Name=Fikrie1
usrgroups= [Windows]
Name=Fikrie2
usrgroups= [Unix]
usrgroups= [Windows]
Name=Lucy
Name=Lucy1

根据我的理解,如果我不按群组查询,它将全部返回。但是,如果我按组添加谓词,那么它将过滤掉用户,包括那些具有空组的用户。这是LEFT类型的加入的默认行为吗?我只想过滤掉有组的用户。对于没有的用户,我不想过滤。是否可以在criteriabuilder中这样做?

更新

我想也许它不是因为外连接而是因为查询本身。为了确认这一点,我在Table User中添加了另一列,如下所示:

     Table User                              
+-------------------------------------------+      
| Name   | Age |  Group        | Skill      |
+-------------------------------------------+     
|Fikrie  | 21  |  Unix         |  <NULL>    |
|Fikrie1 | 22  |  Windows      |  <NULL>    |
|Fikrie2 | 23  |  Unix,Windows |  <NULL>    |    
|Lucy    | 21  |               |  killer    |
|Lucy1   | 22  |               |  <NULL>    |
+-------------------------------------------+

然后我将查询更改为:

    q.select(c);

    Predicate namePredicate = cb.like(c.get(User_.name), "%"
            + nameFilter.toLowerCase() + "%");        
    Predicate skillPredicate = cb.like(c.get(User_.skill),
            "%" + groupFilter.toLowerCase() + "%");        
    Predicate andPredicate = cb.and(namePredicate, skillPredicate);
    q.where(andPredicate);

    List<User> results = em.createQuery(q).setFirstResult(start)
            .setMaxResults(length).getResultList();
    int i = 0;
    for (User usr : results) {
        logger.info("Name=[" + usr.getName() + "], skill=" + usr.getSkill() + "]");

    }
    return results;

这是新测试的日志:

nameFilter = []
groupFilter = []
start is = [0]
length is = [5]

Name=[Lucy], skill=[killer]

我不是100%肯定,但我认为我的查询在处理NULL值时遇到问题。

0 个答案:

没有答案