我有三个域类:Beer,Review和Reviewer。
我希望Review表在Beer和Reviewer之间创建多对多关系,因此我希望Review的主键是Beer和Reviewer的id字段的组合。我正在关注这个Grails文档。
以下是我的域名类。
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)。我想指定索引中列的顺序。
答案 0 :(得分:2)
我已经实施了类似的情况,有一些不同的条件:
hasMany
关系。当这样实现时,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
}
}
我不知道究竟是什么导致了您的问题,但希望这能为您提供有关问题所在的提示。
答案 1 :(得分: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)
答案 2 :(得分:0)
试试这个,在您的域中查看域类:
static constraints = {
review(unique: ['beer','reviewer'])
}
您可能需要删除该表并让Gorm重新创建它。
上述限制意味着评论必须包含啤酒/评论者组合的独特记录。在审稿人有多种啤酒的情况下仍然有很多,反之亦然,但评论是独一无二的。