2010-10-11 21 views
7

我为我的安全框架使用了NimbleShiro,并且我刚刚遇到了一个GORM错误。事实上:GORM createCriteria和list不会返回相同的结果:我该怎么办?

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

最后是你的实现?因为我有同样的问题。非常感谢 – 2011-03-09 09:21:21

回答

4

较少简洁明了,但使用的HQL查询似乎是一个办法来解决这个问题。如Grails documentation(executeQuery部分)中所述,可以将paginate参数作为额外参数添加到executeQuery。

User.executeQuery("select distinct user from User user", [max: 2, offset: 2]) 
+0

非常感谢。有用 !!你知道这个bug是否存在JIRA问题? – fabien7474 2010-10-11 21:41:50

+0

关于为什么listDistinct只在内存中过滤掉重复内容的详细解释可以在Hibernate FAQ中找到:http://community.jboss.org/wiki/HibernateFAQ-AdvancedProblems#Hibernate_does_not_return_distinct_results_for_a_query_with_outer_join_fetching_enabled_for_a_collection_even_if_I_use_the_distinct_keyword。 – Ruben 2010-10-12 05:54:51

0

您可以使用

User.createCriteria().listDistinct { 
    maxResults 10 
} 
+0

几乎工作:)ListDistinct将返回9个用户而不是10个(移除重复的用户)。但是,我怎样才能像偏移参数那样使用分页。 – fabien7474 2010-10-11 11:27:03

+0

这可能会有所帮助:http://grails.org/doc/latest/api/grails/orm/HibernateCriteriaBuilder.html – 2010-10-11 16:25:06

+0

独特投影的问题在于,您只保留独特的“列”或属性指定。 – Ruben 2010-10-11 17:19:13

3

这种方式,你仍然可以使用标准,并通过列表/分页PARAMATERS

User.createCriteria().listDistinct { 
    maxResults(params.max as int) 
    firstResult(params.offset as int) 
    order(params.order, "asc") 
} 
+0

它不仅提供分页参数,其关于有一个真正的PagedResultList与totalCount属性设置... – codewandler 2015-09-15 16:22:31

1

鲁本和亚伦仍然没有“完全”的分页 的工作,因为回到这里提供两种解决方案对象(来自executeQuery()和listDistinct)是一个ArrayList (其中最多可包含max对象),而不是PagedResultList,其totalCount属性为 ,因为我完全支持“分页”。

让我们假设这个例子有点复杂: a。假设角色具有额外的角色名称属性AND 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语句完成上述两个操作?

+0

你可以使用'in'“id”idList而不是循环和idEq(它) – 2011-03-09 09:23:36

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

不幸的是,我不知道如何让在同一个呼叫的全部结果和Max /偏移分页子集的组合。 (任何人谁可以指导呢?)

但是,我可以说,我用一种方式成功地使用分页在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

相关问题