GORM createCriteria and list do not return the same results : what can I do?

前端 未结 6 1507
名媛妹妹
名媛妹妹 2020-12-16 23:51

I am using Nimble and Shiro for my security frameworks and I\'ve just come accross a GORM bug. Indeed :

User.createCriteria().list { 
   maxResults 10 
} 


        
相关标签:
6条回答
  • 2020-12-17 00:25

    Less concise and clear, but using an HQL query seems a way to solve this problem. As described in the Grails documentation (executeQuery section) the paginate parameters can be added as extra parameters to executeQuery.

    User.executeQuery("select distinct user from User user", [max: 2, offset: 2])
    
    0 讨论(0)
  • 2020-12-17 00:25

    You can use

    User.createCriteria().listDistinct {
        maxResults 10
    }
    
    0 讨论(0)
  • 2020-12-17 00:28

    Thanks for sharing your issue and Kok for answering it. I didn't have a chance to rewrite it to HQL. Here is my solution (workaround): http://ondrej-kvasnovsky.blogspot.com/2012/01/grails-listdistinct-and-pagination.html

    Please tell me if that is useful (at least for someone).

    0 讨论(0)
  • 2020-12-17 00:31

    EDIT: Found a way to get both! Totally going to use it now

    http://www.intelligrape.com/blog/tag/pagedresultlist/

    If you call createCriteria().list() like this
    def result=SampleDomain.createCriteria().list(max:params.max, offset:params.offset){
    // multiple/complex restrictions
       maxResults(params.max)
       firstResult(params.offset)
    } // Return type is PagedResultList
    println result
    println result.totalCount
    

    You will have all the information you need in a nice PagedResultList format!

    /EDIT

    Unfortunately I do not know how to get a combination of full results AND max/offset pagination subset in the same call. (Anyone who can enlighten on that?)

    I can, however, speak to one way I've used with success to get pagination working in general in grails.

    def numResults = YourDomain.withCriteria() {
        like(searchField, searchValue)
        order(sort, order)
        projections {
          rowCount()
        }
    }
    
    def resultList = YourDomain.withCriteria() {
        like(searchField, searchValue)
        order(sort, order)
        maxResults max as int
        firstResult offset as int
    }
    

    That's an example of something I'm using to get pagination up and running. As KoK said above, I'm still at a loss for a single atomic statement that gives both results. I realize that my answer is more or less the same as KoK now, sorry, but I think it's worth pointing out that rowCount() in projections is slightly more clear to read, and I don't have comment privileges yet :/

    Lastly: This is the holy grail (no pun intended) of grails hibernate criteria usage references; bookmark it ;) http://www.grails.org/doc/1.3.x/ref/Domain%20Classes/createCriteria.html

    0 讨论(0)
  • 2020-12-17 00:33

    this way you can still use criteria and pass in list/pagination paramaters

    User.createCriteria().listDistinct {
        maxResults(params.max as int)
        firstResult(params.offset as int)
        order(params.order, "asc")
    }
    
    0 讨论(0)
  • 2020-12-17 00:39

    Both solutions offered here by Ruben and Aaron still don't "fully" work for pagination because the returned object (from executeQuery() and listDistinct) is an ArrayList (with up to max objects in it), and not PagedResultList with the totalCount property populated as I would expect for "fully" support pagination.

    Let's say the example is a little more complicated in that : a. assume Role has an additional rolename attribute AND b. we only want to return distinct User objects with Role.rolename containing a string "a" (keeping in mind that a User might have multiple Roles with rolename containing a string "a")

    To get this done with 2 queries I would have to do something like this :

    // First get the *unique* ids of Users (as list returns duplicates by
    // default) matching the Role.rolename containing a string "a" criteria
    def idList = User.createCriteria().list {
      roles {
        ilike( "rolename", "%a%" )
      }
      projections {
        distinct ( "id" )
      }
    }
    
    if( idList ){
      // Then get the PagedResultList for all of those unique ids
      PagedResultList resultList =
        User.createCriteria().list( offset:"5", max:"5" ){
          or {
             idList.each {
               idEq( it )
             }
          }     
          order ("username", "asc")
        }
    }
    

    This seems grossly inefficient.

    Question : is there a way to accomplish both of the above with one GORM/HQL statement ?

    0 讨论(0)
提交回复
热议问题