簡體   English   中英

使用關聯分頁的Grails中的Hibernate Query的不同結果

[英]distinct result in Hibernate Query in grails with pagination using association

我有三個相互關聯的課程。

最初我沒有分頁構建查詢,所有搜索結果都很好。 但現在我需要分頁,不想打擾我的初始查詢模式。 有什么方法可以得到明顯的結果。

Class Department{
    int id;
    String name;
    static hasMany = [courses:Courses]
}

Class Courses{
    String courseName;
    String courseCode;
    static hasMany = [student:Student]
    static belongsTo = [department:Department]
}

Class Student{
    String studentName;
    String address;
    static belongsTo = [courses:Courses]
}


//controller
def list = Department.createCriteria.listDistinct{
    if(params.id){
         and{eq{"id",params.id}}
    }
    and{
        courses{
            if(params.courseName){
                  and{eq("courseName",params.courseName)}
            }
        }
        and{
            student{
                 if(params.studentName){
                         and{eq("studentName",params.studentName)}
                 }
            }
        }
    }
}

我無法給你實際的表格和域名,但這種關系與上面幾乎相同。 它對於dintinct結果非常好,但不能分頁。 我嘗試了一些解決方案,但它返回錯誤。 到目前為止我還沒有記錄任何錯誤。 我已經知道listDistinct不能用於分頁參數。 和列表不提供不同的參數。

我嘗試了投影,但無法像以前一樣檢索所有屬性。 有什么解決方案嗎? 因為我需要從所有可能的屬性中搜索三個表中任何一個的所有實現。 我是否需要將所有查詢切換到另一種方法?

我前段時間遇到類似的任務很困難 - 獲得標准,分頁和獨特的一起工作,解決方案是:1。使用list()而不是listDistinct()2.使用maxResults和firstResult進行分頁3.使用投影{distinct'id'}用於獲取不同的結果4.在獲取id列表后,使用getAll()方法檢索實際對象

加入它將是:

def ids = Department.createCriteria().list() {
    projections {
        distinct 'id'
    }
    maxResults params.max
    firstResult params.offset

    if(params.id){
         and{eq{"id",params.id}}
    }
    and{
        courses{
            if(params.courseName){
                  and{eq("courseName",params.courseName)}
            }
        }
        and{
            student{
                 if(params.studentName){
                         and{eq("studentName",params.studentName)}
                 }
            }
        }
    }
}
return Department.getAll(ids)

(現在沒有測試代碼)

根據文件

listDistinct ()方法不適用於分頁選項maxResult和firstResult。 如果您需要分頁的不同結果,我們目前建議您使用HQL。

試試這個:

def search = Department.createCriteria.list(max: max, offset: offset){
//Enter conditions here
}

然后:

search.unique().totalCount for accessing the total number of results
search.unique() to return back the results.

希望這可以幫助!

干杯

我既不喜歡先查詢查詢完整的ID列表,也不僅僅是一個簡單的listDistinct還不夠 - 因為我需要能夠查詢totalCount

我的策略是

  1. 計數
  2. listDistinct
  3. 將兩者都包裝到PagedResultWrapper中

我想出了一個小GormHelper

package foo
import grails.orm.HibernateCriteriaBuilder
import groovy.util.logging.Log4j
import org.codehaus.groovy.grails.web.util.TypeConvertingMap

/**
 * Gorm Helper
 *
 * @param < T >
 */
@Log4j
class GormHelper<T> {
    /**
     * Clazz the helper will operate on
     */
    private final Class clazz


    private GormHelper(Class<? extends T> clazz) {
        this.clazz = clazz
    }

    /**
     * create a HibernateCriteriaBuilder for the
     * specified clazz
     * @return
     */
    private HibernateCriteriaBuilder createCriteria() {
        return clazz.createCriteria()
    }

    /**
     * List objects by conditions
     * specified in the closure
     * @param params
     * @param closure
     * @return
     */
    List<T> list(Map params, @DelegatesTo(HibernateCriteriaBuilder) Closure closure) {
        createCriteria().list(params, closure)
    }

    /**
     * List all objects
     * @param params
     * @return
     */
    List<T> list(Map params = [:]) {
        return list(params, {})
    }

    /**
     * apply a closure to a HibernateCriteriaBuilder
     * @param crit
     * @param closure
     */
    public static void apply(HibernateCriteriaBuilder crit, Closure closure) {
        if (closure == null) return
        closure.rehydrate(crit, crit, crit).call()
    }

    /**
     * List distinct objects
     * @param _params
     * @param closure
     * @return
     */
    List<T> listDistinct(Map _params, Closure closure) {
        listDistinct(_params, 'id', closure)
    }

    /**
     * List distinct objects
     * @param _params
     * @param distinctProperty
     * @param closure
     * @return
     */
    List<T> listDistinct(Map _params, String distinctProperty, Closure closure) {
        TypeConvertingMap params = new TypeConvertingMap(_params)

        // 1st COUNT
        Integer total = createCriteria().get {
            projections {
                countDistinct(distinctProperty)
            }

            apply(delegate, closure)
        } as Integer

        // 2nd query distinct items with pagination data
        HibernateCriteriaBuilder crit = createCriteria()
        List<T> items = crit.listDistinct {
            apply(delegate, closure)
            setMaxResults(params.int('max'))
            setFirstResult(params.int('offset'))
        }

        // 3rd wrap everything into a PagedResultWrapper
        return PagedResultWrapper.wrap(total, items)
    }

    /**
     * Paged Result Wrapper
     *
     * holds a totalCount beside the data itself
     * can be used as a replacement of the PagedResultList
     */
    public static class PagedResultWrapper extends LinkedList {
        private final Integer total

        /**
         *
         * @param total
         * @param list
         */
        private PagedResultWrapper(Integer total, List list) {
            super()
            this.total = total
            addAll(list)
        }

        /**
         * wrap results and total into a PagedResultWrapper
         * @param total
         * @param collection
         * @return
         */
        public static PagedResultWrapper wrap(Integer total, List collection) {
            return new PagedResultWrapper(total, collection)
        }

        /**
         * get the total count
         * @return
         */
        public int getTotalCount() {
            return total.intValue()
        }
    }

    /**
     * get a Gorm Helper
     * @param clazz
     * @return
     */
    static <V> GormHelper 'for'(Class clazz, Object owner = null) {
        // TODO handle closure ownership
        return new GormHelper<V>(clazz)
    }


}

你會像這樣使用它:

def usersInSelectedGroups = GormHelper.for(User).listDistinct([max: 10, offset: 20]){
  groups {
    inList('id', [1001, 1002, 1003])
  }
}

println "got ${usersInSelectedGroups.totalCount} users"
usersInSelectedGroups.each {println "\t ${it.username}" }

這將輸出具有ID 1001,1002,1003的組中的所有用戶 - 如果用戶是其中幾個組的成員,則它們將僅在結果列表中列出一次 ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM