Grails:一对多关系的排序顺序不起作用

时间:2012-03-26 15:49:35

标签: grails gorm grails-domain-class

我有一个简单的双向一对多映射,如下所示,在拥有方指定了默认排序顺序。但是,排序顺序似乎没有得到应用?我正在使用Grails v2.0.1(我现在用v1.3.7复制了这个例子)。

package playground

class User {

    String name

    static hasMany = [ posts : Post ]

    static mapping = {
        posts sort:'position'
    }
}

package playground

class Post {

    int position = 1
    String message

    static belongsTo = [ user : User ]
}

这是我用来练习它的集成测试代码......

    def User user = new User(name:'bob')
    user.addToPosts(new Post(position:2, message:'two'))
    user.addToPosts(new Post(position:3, message:'three'))
    user.addToPosts(new Post(position:1, message:'one'))

    assertTrue user.validate()
    assertFalse user.hasErrors()
    assertNotNull user.save()

    for (post in user.posts) {
        log.debug "Post message> ${post.message}"
    }

请把我从我的痛苦中解脱出来,这可能是显而易见的但是我看不到它!感谢。

4 个答案:

答案 0 :(得分:7)

使用此代码:

package playground

    class User {

        String name
        static hasMany = [ posts : Post ]

        static mapping = {
            posts sort:'position' order:'desc'//order:'asc'
        }
    }

答案 1 :(得分:1)

事实证明这是一种奇怪的边缘情况行为,这实际上是测试编写方式的结果。基本上,一切都发生在单个Hibernate会话/ txn的范围内(参见上面的对话)。因此,测试将取回刚刚创建的对象图(使用无序Set),而不是从数据库中获取数据。

如果您强制执行单独的事务,则会获得您要查找的行为,并且“order by”按预期工作。 E.g。

User.withNewSession{ session ->
   def User foundUser = User.get(user.id);

   for (post in foundUser.posts) {
      println "Post message> ${post.message}"
   }
}

代码由ndtreviv提供。

答案 2 :(得分:0)

如果您使用列表而不是Set(默认值),框架将为您维护订单。

List posts = new ArrayList()
static hasMany = [ posts : Post ]

答案 3 :(得分:0)

欧文斯的回答让我摆脱了困境。我正在尝试在用户(1)和帖子(很多)之间的关系上定义的排序,但当我编写初始测试时,他们失败了使用用户.get(u.id)是在同一个会话中 - 所以只是从缓存中读出来,然后他们按照我预期的第一个不是最新的顺序回来。

然后我在两个会话中重写了测试,并且在第二个会话中看到这次以desc顺序返回帖子。

所以你必须要小心。如果您在创建帖子的同一原始会话中,则必须使用User.get(u.id).posts.sort()。

所有这些小问题都没有正确理解会话缓存和底层数据库如何在同一会话/事务的范围内工作。有时让你的大脑疼痛。

虽然我们注意到的事情 - 这在3.2.5中的集成测试中出错了,但我发现了Jeff的一个帖子以及已经解决的问题。所以我昨晚升级到了grails 3.2.6,现在这个测试正常工作

void "test query"() {
    given:"a user and where query for users, and posts "
    User u

    when: "create a post for user "
    User.withNewSession { session ->
        u = new User(username: 'will')
        u.save(flush: true, failOnError: true)
        Post p1 = new Post(comment: [food: "bought coffee and cake "])
        Post p2 = new Post(comment: [dinner: "bought wine and dinner"])
        Post p3 = new Post(comment: [view: "spectacular view of lake and sunset"])
        u.addToPosts(p1)
        u.addToPosts(p2)
        u.addToPosts(p3)
        u.save(flush: true)
        if (u.hasErrors())
            println "error saving posts on user u : ${u.errors}"


        def postList = User.get(u.id).posts
        postList.each { println "query via user.list using same session > $it.dateCreated : $it.comment" }

        Post.findAll().each { println "query via Post using same session > $it.dateCreated : $it.comment" }
    }
    //because still in same session it just returns the order from the 1st level cache - so force a
    //new session and let the DB do the sort
    def lookupPosts
    User.withNewSession{ session ->
        User uNew  = User.get(1)
        assert uNew
        lookupPosts = uNew.posts

        lookupPosts.each {println "query via user in new session > $it.dateCreated : $it.comment" }
    }



    then: " check post was added"
    !u.hasErrors ()
    lookupPosts.size() == 3
    lookupPosts[1].comment.dinner == "bought wine and dinner"

}