与Grails hasMany and belongsTo dones创建双向关系';行不通

与Grails hasMany and belongsTo dones创建双向关系';行不通,grails,gorm,Grails,Gorm,我试图在Grails(父-子)中的两个域之间创建一个双向关系,但我似乎无法使其工作。 据我所知,我应该能够在父母和孩子之间创建一个hasMany(父母)和一个belongsTo(孩子)来创建一个双向关系,但这对我来说根本不起作用 我有以下两个领域: class Game { String name String description Double price } class Review { static belongsTo = [game: Game] Str

我试图在Grails(父-子)中的两个域之间创建一个双向关系,但我似乎无法使其工作。 据我所知,我应该能够在父母和孩子之间创建一个hasMany(父母)和一个belongsTo(孩子)来创建一个双向关系,但这对我来说根本不起作用

我有以下两个领域:

class Game {
   String name
   String description
   Double price
}

class Review {
   static belongsTo = [game: Game]
   String reviewText
   Date reviewDate

}
然后我创建了一个
grailsdbmgormdiff文件

databaseChangeLog = {

 changeSet(author: "efx (generated)", id: "1456032538941-1") {
    createTable(tableName: "game") {
        column(name: "id", type: "int8") {
            constraints(nullable: "false", primaryKey: "true", primaryKeyName: "gamePK")
        }

        column(name: "version", type: "int8") {
            constraints(nullable: "false")
        }

        column(name: "description", type: "varchar(255)") {
            constraints(nullable: "false")
        }

        column(name: "name", type: "varchar(255)") {
            constraints(nullable: "false")
        }

        column(name: "price", type: "float8") {
            constraints(nullable: "false")
        }

        column(name: "reviews_id", type: "int8") {
            constraints(nullable: "false")
        }
    }
}

 changeSet(author: "efx (generated)", id: "1456032538941-2") {
    createTable(tableName: "review") {
        column(name: "id", type: "int8") {
            constraints(nullable: "false", primaryKey: "true", primaryKeyName: "reviewPK")
        }

        column(name: "version", type: "int8") {
            constraints(nullable: "false")
        }

        column(name: "review_date", type: "timestamp") {
            constraints(nullable: "false")
        }

        column(name: "review_text", type: "varchar(255)") {
            constraints(nullable: "false")
        }
    }
}

 changeSet(author: "efx (generated)", id: "1456032538941-4") {
    createSequence(sequenceName: "hibernate_sequence")
}

changeSet(author: "efx (generated)", id: "1456032538941-3") {
    addForeignKeyConstraint(baseColumnNames: "reviews_id", baseTableName: "game", constraintName: "FK_jnjkmccicsjmsvqub534xcnnm", deferrable: "false", initiallyDeferred: "false", referencedColumnNames: "id", referencedTableName: "review", referencesUniqueColumn: "false")
}
}

在这一点上,一切都是“完美”的,因此我运行
grials dbm update
以便将更改转移到数据库,但我想使这种关系具有双向性,因此我使用“hasMany”更新我的游戏域,如下所示

class Game {
   static hasMany = [reviews: Review]
   String name
   String description
   Double price
}
在对游戏域进行更改后,我继续运行
grails dbm gorm diff fileupdated.groovy
,这样我最终可以创建双向关系,但得到一个空迁移文件

databaseChangeLog = {
}
注意:即使在游戏域的第一次迁移中使用“hasMany”我收到了相同的结果,也会创建一个关系子-父(游戏评论到游戏),但不会创建父-子(游戏评论到游戏评论)。在教程中,我尝试遵循的方法确实有效。我使用的是grails 2.4.4

为什么没有建立一对一的关系

谢谢,

efx

编辑:

-我创建了一个如下所示的游戏示例,并接收id=1

    groovy:000> g = new com.pluralsight.Game([description: 'Game Desc', name: 'The Game', price: '1.99'])
===> com.pluralsight.Game : (unsaved)
groovy:000> g.save()
===> com.pluralsight.Game : 1
-然后我继续为该游戏创建2个评论,并收到评论id 2和3

    groovy:000> r = new com.pluralsight.Review([game: g, reviewDate: new Date(), reviewText: 'Review 1'])
===> com.pluralsight.Review : (unsaved)
groovy:000> r.save()
===> com.pluralsight.Review : 2

groovy:000> r2 = new com.pluralsight.Review([game: g, reviewDate: new Date(), reviewText: 'Review 2'])
===> com.pluralsight.Review : (unsaved)
groovy:000> r2.save()
===> com.pluralsight.Review : 3
-现在,如果我的双向域名一切正常,我应该能够查询游戏中的所有评论,但我得到一个空值

    groovy:000> retrieve = com.pluralsight.Game.get(1)
===> com.pluralsight.Game : 1
groovy:000> retrieve.reviews
===> null

因此,我不确定为什么我的《从游戏到评论》的《oneToMany》不起作用

为什么你希望数据库会改变

重要的是理解Grails/GORM(和Hibernate)在谈论双向关系时的含义

当关系的两端都有对另一端的引用时,关系被称为双向关系。因此,
游戏
有一组
评论
,而
评论
有对
游戏
的引用。这只涉及应用程序代码。数据库只需要一个外键即可完全存储关系


您也可以使用联接表,但在这种情况下(我认为)这真是太过分了但是Grails/GORM允许它,只需查看文档中如何在
静态映射部分映射它。

正如您所知,一对多关联有两种形式:单向和双向。两者都需要
静态hasMany=…
。只有在双向一对多关联的情况下,
静态ngsTo=…
用于:

单向 双向的 数据库实现 在单向一对多的情况下,您将得到三个表:
game
review
game\u review
game\u review
表通过使用两列(game ID和review ID)来连接其他两个表。
game
review
表保持独立;它们只包含通过
game\u review
表建立关系

在双向一对多模式中,您将得到两个表:
game
review
。但是,
review
表将包含一个外键列:游戏ID。没有联接表使
game
review
表相互独立


我希望这会有所帮助。你可以在我的一篇文章中读到更多关于这方面的信息。

我想感谢@hansboogards和@emmanuelrosa花时间来帮助我,我找到了一篇关于hibernate及其引起的头痛的非常有趣的文章,并找到了我无法从游戏域调用我的评论的原因,因为hibernate没有将它们放在DB上,尽管我我做了拯救

即使在save()之后(没有显式刷新),这将打印空值。只有在刷新会话时,子域实例才会设置其ID。这与我们前面看到的多对一情况完全不同,在这种情况下,不需要显式刷新即可将位置实例持久化到数据库中!重要的是要意识到差异的存在,否则您将失败我会很难过的


我希望能找到一种方法来调用游戏域中的所有评论。让我更新我的示例,以便我能展示我的意思。我对您的编辑和您对Emmanuel Rosa的反应感到有点困惑。似乎您正在groovy shell中尝试grails代码。我认为这不会正常工作。如果您想进行实验,应该使用grails控制台确保所有grails/gorm的“魔法”都有效。Emmanuel Rosa提供的代码应该有效。我们有两个应用程序以相同的结构运行。请记住,hasMany端是关系的所有者。对关系的所有更改都应该通过该端进行。我不明白为什么使用shell而不是控制台会导致问题,当我读到(我可能误解了)控制台是一个相当不错的shell GUI,因此我使用的任何一个都应该给我相同的结果。你用控制台试过了吗?也许我错了,也许不是。我不熟悉用groovy shell做这样的实验。我总是用控制台或编写服务或控制器来测试这样的代码。我不了解这个游戏ew表,如果这是我进行双向配置后应该创建的内容。我将更新问题以显示我的“问题”否,您将获得具有单向配置的game_review表。您必须通过添加它来从游戏的角度保存您的评论:
g.addToReviews(new review(review:date new date)(),reviewText:“Review 1”)
。然后当您保存游戏时,也会保存该评论:
g.save()
@EmmanuelRos
class Game {
   String name
   String description
   Double price

   static hasMany = [reviews: Review]
}

class Review {
   String reviewText
   Date reviewDate    
}
class Game {
   String name
   String description
   Double price

   static hasMany = [reviews: Review]
}

class Review {
   String reviewText
   Date reviewDate

   static belongsTo = [game: Game]
}