7

我将NimbleShiro用于我的安全框架,我刚刚遇到了一个 GORM 错误。确实 :

User.createCriteria().list { 
   maxResults 10 
} 

返回10 个用户,而User.list(max: 10) 返回9 个用户

经过进一步调查,我发现createCriteria 返回两次相同的用户(管理员),因为管理员有 2 个角色!(我不是在开玩笑)。

似乎任何具有超过 1 个角色的用户将在createCriteria调用中返回两次User.list并将返回max-1实例(即 9 个用户而不是 10 个用户)

我可以使用什么解决方法来返回 10 个唯一用户?

这很烦人,因为我无法正确使用分页。


我的域类是:

class UserBase { 
   String username 
   static belongsTo = [Role, Group] 
   static hasMany = [roles: Role, groups: Group] 
   static fetchMode = [roles: 'eager', groups: 'eager'] 
   static mapping = { 
     roles cache: true, 
     cascade: 'none', 
     cache usage: 'read-write', include: 'all' 
   } 
}

class User extends UserBase { 
  static mapping = {cache: 'read-write'} 
} 

class Role { 
  static hasMany = [users: UserBase, groups: Group] 
  static belongsTo = [Group] 
  static mapping = { cache usage: 'read-write', include: 'all' 
    users cache: true 
    groups cache: true 
  } 
} 
4

6 回答 6

4

不太简洁明了,但使用 HQL 查询似乎是解决此问题的一种方法。如Grails 文档(executeQuery 部分)中所述,可以将分页参数作为额外参数添加到 executeQuery。

User.executeQuery("select distinct user from User user", [max: 2, offset: 2])
于 2010-10-11T17:47:59.530 回答
3

这样你仍然可以使用标准并传入列表/分页参数

User.createCriteria().listDistinct {
    maxResults(params.max as int)
    firstResult(params.offset as int)
    order(params.order, "asc")
}
于 2010-10-11T21:28:58.727 回答
2

编辑:找到了两种方法!现在完全打算用

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

您将以漂亮的 PagedResultList 格式获得所需的所有信息!

/编辑

不幸的是,我不知道如何在同一个调用中获得完整结果和最大/偏移分页子集的组合。(任何人都可以启发?)

但是,我可以谈谈我成功使用的一种方法,以使分页在 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
}

这是我用来启动和运行分页的一个例子。正如 KoK 上面所说,我仍然不知道给出两个结果的单个原子语句。我意识到我的答案现在或多或少与 KoK 相同,抱歉,但我认为值得指出的是,预测中的 rowCount() 阅读起来稍微清晰一些,而且我还没有评论权限:/

最后:这是 grails 休眠标准使用参考的圣杯(不是双关语);收藏它;) http://www.grails.org/doc/1.3.x/ref/Domain%20Classes/createCriteria.html

于 2011-11-17T20:27:33.843 回答
1

Ruben 和 Aaron 提供的两种解决方案仍然不能“完全”用于分页,因为返回的对象(来自 executeQuery() 和 listDistinct)是一个 ArrayList(其中最多包含最大对象),而不是具有 totalCount 属性的 PagedResultList正如我对“完全”支持分页所期望的那样填充。

假设这个例子稍微复杂一点:假设角色有一个额外的角色名称属性和 b。我们只想返回具有包含字符串“a”的 Role.rolename 的不同用户对象(请记住,用户可能有多个角色,其角色名称包含字符串“a”)

要通过 2 个查询完成此操作,我必须执行以下操作:

// 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")
    }
}

这似乎非常低效。

问题:有没有办法用一个 GORM/HQL 语句来完成上述两个任务?

于 2010-11-22T14:45:04.927 回答
0

您可以使用

User.createCriteria().listDistinct {
    maxResults 10
}
于 2010-10-11T10:51:48.230 回答
0

感谢您分享您的问题和 Kok 的回答。我没有机会将其重写为 HQL。这是我的解决方案(解决方法): http: //ondrej-kvasnovsky.blogspot.com/2012/01/grails-listdistinct-and-pagination.html

请告诉我这是否有用(至少对某人)。

于 2012-01-20T13:55:35.183 回答