![](/img/trans.png)
[英]Issue with multiple hasMany relationships to the same domain class when using composite id
[英]Multiple hasMany relationships to same domain class in Grails
我正在使用Grails,并且我有一个具有多个hasMany属性的域模型到同一个域类,如下所示:
static hasMany = [ posts : Post, likes : Post, dislikes : Post ]
我遇到的问题是,当我在帖子列表中添加内容时,它也会以某种方式将其变成喜欢和不喜欢的列表。 至少,当我遍历每个列表时,它就是这样的样子。
我认为问题是我在Post域中也有以下关系:
static belongsTo = [ contributer : Contributer ]
配置这些关系以使我的模型工作的最佳方法是什么? 有什么建议?
@Wayne,
我也试过使用你的测试,它成功通过了。 所以,我唯一能想到的是我的PostController中的save方法有问题。 我已粘贴下面的相关代码(我正在使用Spring Security Core插件,而我的Contributer类扩展了使用该插件创建的User类):
@Secured(['IS_AUTHENTICATED_FULLY'])
def save = {
def props = [title:params.title, post:params.post, category:Category.get(params.category.id)]
def user = Contributer.get(springSecurityService.principal.id)
def postInstance = new Post(props)
postInstance.contributer = user
if (postInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'post.label', default: 'Post'), postInstance.id])}"
redirect(action: "show", id: postInstance.id)
}
else {
render(view: "create", model: [postInstance: postInstance])
}
}
有什么突出的吗?
问题是你在Post和Contributor之间有一对多(帖子有作者,作者有很多帖子)以及Post和Contributor之间有两对多关系(帖子有很多喜欢的帖子,像很多帖子一样)(帖子)有很多不喜欢的人,不喜欢很多帖子。 Post中的belongsTo
确实解释了行为,但删除它不会解决问题,只需创建不同的问题。 最终结果是GORM约定将会失败,因此您必须告诉GORM如何对事物进行不同的行为或建模。
有几个选项,而是跳转到心中的一个是从后分别模拟投票,并让这个贡献者hasMany
likeVotes和hasMany
dislikeVotes
class Vote {
// for illustration here, you need to think about the
// cascading behavior that makes sense and model it if you decide
// to go this route.
belongsTo = [post, contributor]
}
class LikeVote extends Vote {
}
class DislikeVote extends Vote {
}
GORM会将此模型建模为一个带有鉴别器列的投票表,以区分好恶; 这样可以消除喜欢,不喜欢和创作帖子之间的冲突。
然后在贡献者
hasMany = [likes:LikeVote, dislikes:DislikeVote, posts:Post]
现在关系清理了:
GORM可以理解这些关系并且行为恰当。
如果您不喜欢此选项,则下一步是为数据库结构指定自定义映射,然后使用mappedBy
区分各种关系。 如果您绝对希望让投稿人以三种不同的方式直接与Post相关,那么这就是您要采取的方法。
在域类中使用static mappedBy
例如:
在许多侧域对象( Contributer.groovy )中:
static hasMany = [ posts : Post, likes : Post, dislikes : Post ]
static mappedBy = [posts: "postsContributer", likes: "likesContributer", dislikes: "dislikesContributer"]
在一个侧域对象( Post.groovy ):
Class Post {
static belongsTo = [ contributer : Contributer ]
Contributer postsContributer
Contributer likesContributer
Contributer dislikesContributer
...
}
虽然,多M:M的标准方法是使用joinTable ,如GRAILS-4884中所推荐的那样 。
这应该有效:
static hasMany = [ posts : Post, likes : Post, dislikes : Post ]
static mapping = {
posts joinTable: [name: 'contributor_posts']
likes joinTable: [name: 'contributor_likes']
dislikes joinTable: [name: 'contributor_dislikes']
}
你能证明测试用例失败了吗? 我把我认为你的情况放到了grails 1.3.7项目中,测试通过:
class Post {
String text ="postal"
static belongsTo = [ contributor : Contributor ]
static constraints = { }
}
class Contributor {
String name = "Big C"
static hasMany = [ posts : Post, likes : Post, dislikes : Post ]
static constraints = { }
}
// integration test
void testMultipleRel() {
Contributor c = new Contributor().save()
assertNotNull c
Post p1 = new Post(text:"neutral")
Post p2 = new Post(text:"like")
Post p3 = new Post(text:"dislike")
[p1,p2,p3].each {c.addToPosts(it).save()}
assertNotNull p1
assertNotNull p2
assertNotNull p3
assertNull c.likes
assertNull c.dislikes
c.addToLikes(p2)
c.addToDislikes(p3)
assertEquals ([p1, p2, p3] as Set, c.posts as Set)
assertEquals ([p2] as Set, c.likes as Set)
assertEquals ([p3] as Set, c.dislikes as Set)
}
尝试切换到多对多关系并定义映射域类。 在此映射域类中,您可以指定关系类型; 喜欢,不喜欢或作者。
class Contributor {
static hasMany = [contributorPosts:ContributorPost]
}
class ContributorPost {
Post post
Contributor contributor
Boolean like
Boolean dislike
Boolean author
}
class Post {
static hasMany = [contributorPosts:ContributorPost]
}
您可以在这里查看http://www.grails.org/Many-to-Many+Mapping+without+Hibernate+XML,以获取有关多对多映射域类的更多信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.