[英]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 。
我的策略是
我想出了一個小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.