Grails:创建多对多对多关系?

Grails: creating a many-to-many-to-many relationship?

所以我目前正在构建一个 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? []

问题很可能是 save() 函数没有 return 保存的对象。

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

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

哪个编译了。但是,还有一个问题 - 您必须设置 new_post 的 运行 user.addToCreated_posts 而不是 运行 creator,因为您没有明确地设置在您创建 Post 域 class 时指定它可以为 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())

我这样做的原因是你不是在拯救用户——你是在拯救 post。当您为用户创建 posts 时,Grails 会在数据库中搜索 posts,其中 creator_id 列设置为您从中调用该方法的用户的 ID。

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

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

您绝对需要Post.groovy以下内容:

static belongsTo = [creator: User]

这样,Grails 就知道应该如何为用户查找 Posts。

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