【问题标题】:Wrong pagination result when removing duplicate records删除重复记录时分页结果错误
【发布时间】:2015-10-18 03:28:04
【问题描述】:

我将以下标准与分页参数一起使用。由于加入而产生了一些重复记录,所以我使用了setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)。它删除了重复记录,但似乎在应用分页后删除了重复记录。

例如:如果 offset 为 20,max 为 10。这意味着它应该获取 20-30 条记录。但是假设记录 28,29 和 30 是重复的,因此它们被删除并且在页面中仅显示 20-27 记录。所以第三页只显示 20-27 条记录,即使这些记录不是最后的。

  return Question.createCriteria().list(offset: offset,max: max) {
        createAlias("questionHistory","qh")
        if(createdStartDate!=null){
            ge('createdDate',createdStartDate)
        }
        if(createdEndDate!=null){
            le('createdDate',createdEndDate)
        }
        if(folderId>0){
            eq('folder.id',folderId)
        }else if(itemBankId>0){
            or{
                folders.each {
                    eq('folder.id',it.id)
                }
            }
        }
      ....
      ......
       if(authorIds?.size()>0){
            'in'("qh.changedBy.id",authorIds)
        }
      ..........
      ..................
      ....................................
       setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
    }

我知道原因是因为首先执行条件,然后删除重复记录。有没有办法获取下一个记录(如果有)等于找到的重复记录的数量?

【问题讨论】:

    标签: hibernate grails pagination criteria hibernate-criteria


    【解决方案1】:

    遗憾的是,我从未成功完成这项工作。当连接和分页混合在一起时,Hibernate 会丢失,实际上我认为它一定是:AFAIK 解决同一域类实例具有多行问题的唯一方法是检查域类并查看它是否有一个主键,然后通过它聚合结果。我不确定这是否总是可能的。

    无论如何,我“解决”这个问题的方法是创建一个单独的查询来评估条件,然后创建一个查询来应用分页(这可以触发另一个用于计算结果的查询)。

    所以使用描述失败案例的要点:https://gist.github.com/deigote/549dcecdbb2a6ba80074

    我会通过以下方式解决它:

    def matchedIds = Car.createCriteria().list([:]) {
       distinct 'id'
       createAlias('brands', 'brands', CriteriaSpecification.INNER_JOIN)
       ... // criterias here
    }
    
    def actualResults = Car.createCriteria(max: maxResults, first: firstResults).list {
      'in'('id', matchedsIds)
    }
    

    actualResults 包含当前“页面”结果,并允许您调用 totalCount 以获取结果总数。

    【讨论】:

      【解决方案2】:

      我已经解决了。我没有在 list() 中使用分页参数,而是使用了 setFirstResult/setMaxResults。但缺点是它没有给出 'totalCount' 值,因此需要为它触发单独的查询。

      解决方案:

      setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
      setFirstResult(offset)
      setMaxResults(max)
      

      它首先删除重复项,然后应用分页给出正确的结果。

      【讨论】:

      • 不错。我一直认为我必须做 2 个查询,第一个包含所有条件和一个不同的 'id' 投影,第二个只有一个“'in'(id', listOfIdsFromTheFirstQuery)”和分页。我认为为 totalCount 做一个单独的应该没问题。感谢分享。
      • 你好,我试过了,但没有用 :-(。我在这里反映了我的失败案例:gist.github.com/deigote/549dcecdbb2a6ba80074 你能在你的场景中尝试这样的事情吗?
      【解决方案3】:

      加入集合时很难实现分页;另一种方法是使用子查询,如here 所述。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-17
        • 2017-04-25
        • 1970-01-01
        • 2016-01-07
        • 1970-01-01
        • 2012-05-11
        相关资源
        最近更新 更多