5

我有三个域类:Beer、Review 和 Reviewer。

我希望 Review 表在 Beer 和 Reviewer 之间创建多对多关系,因此我希望 Review 的主键是 Beer 和 Reviewer 的 id 字段的组合。我正在关注这个 Grails 文档。

http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.5.2.5%20Composite%20Primary%20Keys

这是我的域类。

class Beer {
    String name
    String type
    Brewery breweryId

    static hasMany = [ reviews : Review ]

    static constraints = {
    }
}

class Reviewer {
    String screenName

    static hasMany = [ reviews : Review ]

    static constraints = {
    }
}

class Review implements Serializable {
    int score
    Beer beer
    Reviewer reviewer


    static constraints = {
    }

    static mapping = {
        id composite:['beer', 'reviewer']
    }
}

我遇到了编译错误,但是 stackoverflow 上的另一个答案说我需要添加implements Serializable. 这解决了错误,但是当我查看数据库时,我仍然没有得到复合主键。

这是我查看表定义时看到的内容。我正在使用 Postgres。

       Table "public.review"
   Column    |  Type   | Modifiers 
-------------+---------+-----------
 id          | bigint  | not null
 version     | bigint  | not null
 beer_id     | bigint  | not null
 reviewer_id | bigint  | not null
 score       | integer | not null
Indexes:
    "review_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "fkc84ef75823f39326" FOREIGN KEY (beer_id) REFERENCES beer(id)
    "fkc84ef7587c483106" FOREIGN KEY (reviewer_id) REFERENCES reviewer(id)

我很乐意只使用具有唯一约束的复合索引,但我也不知道如何做到这一点。我已经能够制作一个非唯一的复合索引,但这有两个问题。一,它是非唯一的。二、列在索引中按字母顺序指定(beer_id、reviewer_id)。我想指定索引中列的顺序。

4

3 回答 3

2

我已经实现了类似的情况,但有一些不同的条件:

  1. 没有hasMany关系。
  2. 对连接类的查询由 HQL 完成
  3. 使用更详细的映射

当这样实现时,mysql数据库就可以了。(beer_id,reviewer_id) 是主键。

class Review implements Serializable {

    Beer beer
    Reviewer reviewer

    static Review get(long beerId, long reviewerId) {
        find 'from Review where beer.id=:beerId and reviewer.id=:reviewerId',
            [beerId: beerId, reviewerId: reviewerId]
    }

    static boolean remove(Beer beer, Reviewer reviewer, boolean flush = false) {
        Review instance = Review.findByBeerAndReviewer(beer, reviewer)
        instance ? instance.delete(flush: flush) : false
    }
    ...

    static mapping = {
        table "REVIEW"
        id composite: ['beer', 'reviewer']
        beer(column: "beer_ID")
        reviewer(column: "reviewer_ID")
        version false
    }
}

我不知道究竟是什么导致了你的问题,但希望这能给你一些关于问题所在的提示。

于 2011-04-01T03:06:49.573 回答
2

我接受了 Grails 的命令,即我不应该使用复合主键作为明智的建议,并且正在避免它。如果是这样,我相信解决您的问题的可行替代方案是复合唯一约束。参考: http: //grails.org/doc/1.1.x/ref/Constraints/unique.html

Jacco 的答案似乎不正确,尽管它在视觉上看起来非常接近正确,但您可以通过以下方式为该问题编写复合唯一约束:

static constraints = {
    beer(unique: 'reviewer')
}

而如果程序员想要将 3 个 db 字段链接为唯一的,则正确的格式是:

static constraints = {
    beer(unique: ['anotherField','reviewer'])
}

看起来像 Jacco 的答案,但类名不用作约束的第一个字符串,而是使用第一个字段名。

我刚刚在我自己的项目应用程序中使用了这个代码结构,它似乎表现正确,另请参阅如何对唯一约束进行单元测试:http: //www.ibm.com/developerworks/java/library/j -grails10209/index.html (参见清单 11)

于 2011-09-12T03:47:19.060 回答
0

试试这个,在您的域中查看域类:

static constraints = {
     review(unique: ['beer','reviewer'])
}

您可能需要删除表并让 Gorm 重新创建它。

上述约束意味着评论必须包含啤酒/评论者组合的唯一记录。评论者有多种啤酒的情况仍然很多,反之亦然,但评论是独一无二的。

于 2011-03-31T18:56:23.143 回答