【问题标题】:Grails: multiple relationships between two domain objectsGrails:两个域对象之间的多重关系
【发布时间】:2013-04-16 23:02:28
【问题描述】:

我正在尝试在 Grails 中的两个域类之间实现两种不同类型的关系。

考虑以下事项;我有两个域类,一个 Author 和 Book 类,一个 Author 有很多书。

class Author{           
   String name 
}

class Book{
   String title
   static belongsTo = [author:Author]

}

上面描述了作者和书籍之间非常基本的一对多关系。 但我也希望作者有一个最喜欢的书籍列表的概念。理想情况下,这将被表示为一个单独的一对多关系,将同一个 Book 对象描述为一个列表并保持不变。

class Author{          
   String name
   static hasMany = [favouriteBooks: Book]

   static mapping = {
        favouriteBooks joinTable: [name: 'favourite_books',
                key: 'author_id']
   }
}

class Book{
   String title
   static belongsTo = [client:Client]

}

我已尝试如上描述这一点(在许多其他方法中),最终没有创建数据库表(favourite_books)。我没有收到任何错误。这是我能想到的唯一方法,无需使用任何额外的对象,我想避免使用任何额外的对象来保持模型简单。 我觉得我在正确的轨道上,但可能错过了一些重要的拼图。

任何帮助将不胜感激。

【问题讨论】:

  • 您是否尝试过再次clean、exit、grails,然后run-app。有时 grails 在没有 clean 的情况下不会获取您的域更改
  • 在上面的第一个示例中,您缺少Author 端的hasMany 属性,而在第二个示例中,Book 端没有引用favouriteBooks 关系。

标签: grails grails-orm


【解决方案1】:

首先,让我们确保我正确理解了您的问题。你有BookAuthor 域类,但是这些类之间有两种关系:

  1. 作者写书,所以AuthorBook 之间存在一对多的关系。当然,在现实生活中,一本书可能由许多作者撰写,但在这种情况下,我们似乎可以忽略这一点。
  2. 作者有最喜欢的书,因此AuthorBook 之间存在第二个多对多关系。这种关系是多对多的,因为某本书可能是许多作者的最爱。

所以假设我已经正确理解了这个问题,让我们试着找到一个解决方案。首先,让我们添加多对多的关系(最喜欢的书):

class Author {
    String name
    static hasMany = [favourites: Book]
}

class Book {
    String title
    static hasMany = [favouritedBy: Author]
    static belongsTo = Author
}

只要定义了多对多关系,我们就必须选择一方作为关系的所有者。在这种情况下,我指定了

static belongsTo = Author

Book 类中,所以Book 是关系的拥有方,Author 是所有者。因此,我们应该向作者添加最喜欢的书籍,而不是相反,see here 了解更多详情。

然后可以添加一对多关系:

class Author {
    String name
    static hasMany = [favourites: Book, booksWritten: Book]
}

class Book {
    String title
    static hasMany = [favouritedBy: Author]
    static belongsTo = Author

    Book writtenBy
}

顺便说一句,在您的域模型中,您在 Author 类中包含以下内容

static mapping = {
    favouriteBooks joinTable: [name: 'favourite_books', key: 'author_id']
}

这将导致连接表被命名为favourite_books,而在我的模型中连接表将默认为author_favourites。如果出于某种原因您特别希望连接表以这样的方式命名(例如,您尝试将类映射到现有表),请随意包含上述内容。

最后,如果您发现自己在定义域类映射时遇到了困难,并且更愿意创建表,然后从中生成域类,请查看this plugin

【讨论】:

  • 感谢您快速详细的回复。您对我想要实现的目标的解释是正确的,虽然它有效,但我似乎对这种方法有一个小问题。我似乎最终得到了一个单独的 author_books_written 表来映射作者对一本书的所有权。我希望在我的 Books 表中有一个 author_id?有可能解决这个问题吗?
  • 顺便说一下,我们可以假设一本书只能有一个作者。
【解决方案2】:

终于想通了。 感谢 Don 为我指明了 db-reverse-engineer 插件的方向,它帮助公开了允许这种映射策略的关键属性。 基本上,这一切都归结为使用 GORM 的 mappedBy 关联设置来明确告诉 Grails 如何映射多个 hasMany 引用。 起作用的类文件如下:

class Author {

    String name
    static hasMany = [books: Book, favourites: Book]

    // need to disambiguate the multiple hasMany references with the 
    // 'mappedBy' property:
    static mappedBy =   [books: "author",
                        favourites: "authors"]
}

class Book {

    String title
    Author author

    static hasMany = [authors: Author]
    static belongsTo = [Author]
}

再次感谢您的帮助

【讨论】:

    【解决方案3】:

    修改Book域类。删除author 映射。

    class Book{
       String title
       static belongsTo = [Author]
    }
    

    查找新表 FAVORITE_BOOKS 一次 cleanrun-app

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-11
      • 2019-02-01
      • 1970-01-01
      • 2017-06-26
      • 1970-01-01
      相关资源
      最近更新 更多