Grails:创建多对多关系?

时间:2017-03-23 04:15:30

标签: grails gorm relationship has-many belongs-to

所以我目前正在构建一个Grails应用程序,我正在尝试允许用户创建帖子,这些帖子也有评论。

我想要创建的关联类似于:

用户可以有0到多个帖子,和 帖子可以有0到多个评论

我尝试使用我的域类进行设置,如下所示:

class User implements Serializable{
    static hasMany = [created_posts: Post]
    String username
    String password
}

class Post {
    static hasMany = [comments: Comment]
    String description
}

class Comment {
    String comment_body
    static belongsTo = [post: Post]
}

我也尝试使用mappedBy属性,如下所示:

class User implements Serializable{
    static hasMany = [created_posts: Post]
    static mappedBy = [created_posts: 'creator']
    String username
    String password
}

class Post {
    static hasMany = [comments: Comment]
    static belongsTo = [creator: User]
    String description
}

class Comment {
    String comment_body
    static belongsTo = [post: Post]
}

但它仍然无效。我用来创建它的代码如下:

Post new_post = new Post(description: "testing").save()
User user = User.get(springSecurityService.principal.id)
user.addToCreated_posts(new_post).save()

不幸的是,Grails似乎无法执行最后一行,有时它根本无法编译,从而产生:bootRun错误。

我不确定如何在用户,帖子和评论之间创建正确的关联。欢迎任何帮助,非常感谢!

编辑:我当前的代码:(编译,但不保存到用户设置)

class User implements Serializable{
    static hasMany = [createdPosts: Post]
    static mappedBy = [createdPosts: 'creator']
    String username
    String password
}

class Post {
    static hasMany = [comments: Comment]
    static belongsTo = [creator: User]
    String description
    static constraints = { creator nullable: true }
}

class Comment {
    String comment_body
    static belongsTo = [post: Post]
}

我在控制器中使用的代码:

User user = User.get(springSecurityService.principal.id)
Post new_post = new Post(description: "testing description", creator: user).save()
user.save()
System.out.println("post saved to user? " + user.getCreatedPosts())

输出是:

post saved to user? []

1 个答案:

答案 0 :(得分:1)

问题很可能是save()函数没有返回保存的对象这一事实。

最初,我将您的代码更改为:

Post new_post = new Post(description: "testing")
new_post.save()
User user = User.get(springSecurityService.principal.id)
user.addToCreated_posts(new_post).save()

哪个编译了。但是,还有一个问题 - 您不必运行user.addToCreated_posts,而是必须设置new_post的属性creator,因为您在创建Post域时没有明确指定它可以为null类。因此,对save()的调用将无声地失败。

如果您将代码更改为:

User user = User.get(springSecurityService.principal.id)
Post new_post = new Post(description: "testing", creator: user)
new_post.save()

您的代码应该有效。

save()的所有调用替换为save(failOnError: true)也是一个好主意,这样当保存失败时,就会抛出异常。您可以捕获此异常,并从异常中提取错误消息。通常,错误消息与域对象的失败验证有关。

这是在Grails 3.2.7上使用H2(与Grails打包的默认内存数据库)进行测试的。

编辑以下是基于对问题所做更新的更新代码段。

您正在运行:

User user = User.get(springSecurityService.principal.id)
Post new_post = new Post(description: "testing description", creator: user).save()
user.save()
System.out.println("post saved to user? " + user.getCreatedPosts())

我会将其更改为:

User user = User.get(springSecurityService.principal.id)
Post new_post = new Post(description: "testing description", creator: user)
new_post.save(failOnError: true)
System.out.println("post saved to user? " + user.getCreatedPosts())

我这样做的原因是因为您没有保存用户 - 您正在保存帖子。当您为用户创建帖子时,Grails会在数据库中搜索其中creator_id列设置为您调用该方法的用户的ID的帖子。

另外,我确保您没有从User.groovy中删除以下行:

static hasMany = [createdPosts: Post]
static mappedBy = [createdPosts: "creator"]

你绝对需要以下Post.groovy:

static belongsTo = [creator: User]

这样,Grails知道如何为用户查找帖子。

进行这些更改后,请确保从新的数据库开始 - 对于内存中的H2,这应该自动完成,只要您使用开发环境 - 并重新启动服务器。