我正在尝试使用Grails开发一个安静的服务器,但我无法正确获取域类。我使用的是Grails 2.4.2。
我将有一个Story类和一个User类。 Story类将有一个"作者"哪个是User类型。它还将有许多编辑和#34;和许多观众"这将是一组用户。我已经尝试了很多不同的方法来描述Groovy for GORM转换为mySQL,但每个问题都出现了不同的问题。以下情况似乎是我最接近一个好的解决方案,但我遇到了障碍。如果我删除了一个也在Story实例的编辑器集合中的User实例,我得到了
Cannot delete or update a parent row: a foreign key constraint fails (`test`.`editor`, CONSTRAINT `FK_jhrniu8kj891sx2i73mgtgc0v` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)); nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`editor`, CONSTRAINT `FK_jhrniu8kj891sx2i73mgtgc0v` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`))
我怎样才能让它发挥作用?我认为Editor.groovy中的belongsTo
指向User会级联删除。我愿意更好地设置域类,因为我对Grails和GORM来说相对较新。
以下是代码:
Story.groovy
class Story {
String title
User author
static belongsTo = [User]
static hasMany = [viewers: Viewer, editors: Editor]
static constraints = {
viewers nullable: true
editors nullable: true
}
}
User.groovy
class User {
String username
static hasMany = [stories : Story]
static constraints = {
username nullable:false
}
}
Editor.groovy
class Editor {
User user
static belongsTo = [story: Story, user: User]
static constraints = {
}
}
测试代码:
void "Testing removal of a user and editors"() {
given: "New Users, New Story"
def joe = new User(username:"joe").save(failOnError: true)
def jane = new User(username:"jane").save(failOnError: true)
def bill = new User(username:"bill").save(failOnError: true)
def story1 = new Story(author: joe, title:"Story1 Title").save(failOnError: true)
when: "let's add some editors and then delete a user"
story1.addToEditors(new Editor(user: jane))
story1.addToEditors(new Editor(user: bill))
story1.save(failOnError: true, flush: true)
assert story1.editors.size() == 2
println("before bill deleted " + story1.dump())
bill.delete(flush: true) //<-ERROR occurs here
then: "Should only be one editor now"
println("after bill deleted:" + story1.dump())
story1.errors.errorCount == 0
story1.editors.size() == 1
}
我尝试在User中添加一个beforeDelete闭包,但是我得到了同样的错误。
def beforeDelete = {
Editor.findAllByUser(it)*.delete()
}
答案 0 :(得分:0)
belongsTo
课程中的Story
为BelongsTo
而不是belongsTo
。它必须是belongsTo
。
答案 1 :(得分:0)
我不知道这是不是最好的方法。一位朋友提到组织域类有点不同,并实现一些getter和setter。它让我想起了Spring Security Core中使用的角色,所以我查看了该模块中的UserRole类,发现他们在User,Role和UserRole之间的关系中没有使用belongsTo
或hasMany
。事实上,我做了一个测试,我创建了一个UserRole然后尝试删除User而不删除UserRole,我得到了相同的a foreign key constraint fails
错误。在这个方向上,我创建了以下代码,通过了集成测试,但我没有得到contraint fails
错误。这是一个更多的工作。也许当我更好地理解GORM时,我可以简化这一点。 (我从Spring Security Core借用了removeAll方法)
class Story {
def roleService
String title
static constraints = {
}
def getEditors() {
roleService.findAllByStory(this, Role.EDITOR)
}
def addToEditors(User u) {
roleService.addToRole(u, this, Role.EDITOR)
}
def removeEditor(User u){
roleService.removeRole(u, this, Role.EDITOR)
}
def beforeDelete() {
def story = this
Story.withNewSession {
Editor.removeAll(story, true)
Viewer.removeAll(story, true)
}
}
//TODO add getters and setters for Viewers and Authors
}
User.groovy
class User {
String username
static constraints = {
username nullable:false
}
}
Role.groovy
class Role {
User user
Story story
static constraints = {
}
static void removeAll(Story s, boolean flush = false) {
if (s == null) return
Role.where {
story == Story.load(s.id)
}.deleteAll()
if (flush) { Role.withSession { it.flush() } }
}
//TODO implement removeAll(User u, boolean flush=false)
static final int EDITOR = 1
static final int VIEWER = 2
static final int AUTHOR = 3
}
Editor.groovy
class Editor extends Role{
static constraints = {
}
}
Viewer.groovy
class Viewer extends Role{
static constraints = {
}
}
RoleService.groovy
@Transactional
class RoleService {
public findAllByStory(Story s, int role){
switch (role ){
case Role.EDITOR:
return Editor.findAllByStory(s).collect {e -> e.user}
break;
case Role.VIEWER:
return Viewer.findAllByStory(s).collect {v-> v.user}
break;
}
}
public addToRole(User u, Story s, int role){
switch (role ){
case Role.EDITOR:
new Editor(user: u, story: s).save()
break;
case Role.VIEWER:
new Viewer(user: u, story: s).save()
break;
}
}
public removeRole(User u, Story s, int role){
if(u == null || s == null) {return false}
switch (role ){
case Role.EDITOR:
Editor.where {
user.id == u.id &&
story.id == s.id
}.deleteAll()
break;
case Role.VIEWER:
Viewer.where {
user.id == u.id &&
story.id == s.id
}.deleteAll()
break;
}
}