带有多个belongsTo的类级别删除的Grails问题

时间:2014-10-01 18:41:57

标签: grails gorm

我正在尝试使用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()

        }

2 个答案:

答案 0 :(得分:0)

belongsTo课程中的StoryBelongsTo而不是belongsTo。它必须是belongsTo

答案 1 :(得分:0)

我不知道这是不是最好的方法。一位朋友提到组织域类有点不同,并实现一些getter和setter。它让我想起了Spring Security Core中使用的角色,所以我查看了该模块中的UserRole类,发现他们在User,Role和UserRole之间的关系中没有使用belongsTohasMany。事实上,我做了一个测试,我创建了一个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;
        }
    }