我正在使用Nimble和Shiro作为我的安全框架,而我刚刚遇到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
}
}
答案 0 :(得分:4)
简洁明了,但使用HQL查询似乎是解决此问题的一种方法。如Grails documentation(executeQuery部分)中所述,可以将paginate参数作为额外参数添加到executeQuery中。
User.executeQuery("select distinct user from User user", [max: 2, offset: 2])
答案 1 :(得分:3)
这样你仍然可以使用标准并传入列表/分页参数
User.createCriteria().listDistinct {
maxResults(params.max as int)
firstResult(params.offset as int)
order(params.order, "asc")
}
答案 2 :(得分: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格式获得所需的所有信息!
/ EDIT
不幸的是,我不知道如何在同一个调用中获得完整结果和最大/偏移分页子集的组合。 (任何可以启发的人?)
然而,我可以用一种方式来说明我在成功时使用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 hibernate标准用法参考的圣杯(没有双关语);给它添加书签;) http://www.grails.org/doc/1.3.x/ref/Domain%20Classes/createCriteria.html
答案 3 :(得分:1)
Ruben和Aaron在这里提供的两种解决方案仍然没有“完全”用于分页 因为返回的对象(来自executeQuery()和listDistinct)是一个ArrayList (最多包含最大对象),而不是具有totalCount属性的PagedResultList 正如我所期望的那样填充“完全”支持分页。
让我们说这个例子有点复杂: 一个。假设Role具有另外的rolename属性AND 湾我们只希望返回包含字符串“a”的Role.rolename的不同User对象 (请记住,用户可能有多个角色,其角色名称包含字符串“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语句完成上述两个步骤?
答案 4 :(得分:0)
您可以使用
User.createCriteria().listDistinct {
maxResults 10
}
答案 5 :(得分:0)
感谢您分享您的问题和Kok回答它。我没有机会将它重写为HQL。这是我的解决方案(解决方法):http://ondrej-kvasnovsky.blogspot.com/2012/01/grails-listdistinct-and-pagination.html
请告诉我这是否有用(至少对某人而言)。