grails复合密钥更新

时间:2012-08-15 08:29:54

标签: grails gorm

我有一个遗留数据库,我正在使用Grails。错误#1。

它使用复合键。错误#2。

鉴于这些域类:

Movie {
    static hasMany = [ roles: Role ]
}
Person {
    static hasMany = [ roles: Role ]
}
Role {
    Movie movie
    Person person
    String foo
}

我想将角色从一个人转移到另一个人,就像这样:

Role x = person1.roles[0]
x.person = person2
save(flush:true)

但没有任何反应。完全没有。我在log4j中打开了hibernate的跟踪和调试级别日志记录,它没有显示更新语句。但是,如果我这样做:

Role x = person1.roles[0]
x.person = person2
x.foo = "i can haz update?"
save(flush:true)

foo会发生更新,但不会修改指向person的外键,如下所示:

DEBUG hibernate.SQL  - update ct_roles set foo=? where movie_id=? and person_id=?
TRACE sql.BasicBinder  - binding parameter [1] as 'i can haz update?'
TRACE sql.BasicBinder  - binding parameter [2] as [BIGINT] - 999
TRACE sql.BasicBinder  - binding parameter [3] as [BIGINT] - 2

请注意,person_id 2属于person2,目前尚无角色,因此更新失败。

因此,如果没有简单地删除旧角色并创建一个附加到所需人员的新角色,有没有办法解决这个问题?

2 个答案:

答案 0 :(得分:0)

尝试:

person1.removeFromRoles(role) // role是要从中删除人员的角色对象
role.person = person2

应该工作。

答案 1 :(得分:0)

答案是:

class Role { 
    Movie movie
    Person person
    String fuGorm

    def move(Person newbie) {
        def m = this.movie?.id
        def p = this.person?.id
        def n = newbie?.id

        // bypass GORM and issue a raw SQL update command...
        def q = "update ct_roles set person_id=$n where person_id=$p and movie_id=$m"
        def success = runCommand(q)

        if (success) {
            // the above bypasses GORM, so we should still
            // perform the operation using GORM speak
            // otherwise our objects will be out of sync with the DB.
            // The following EPIC FAILS to update the DB, 
            // but it does update the local Grails domain objects
            this.person.removeFromRoles(this)
            this.person = newbie
            newbie.addToRoles(this)
        }
        return success
    }
    def runCommand = { query ->
        def db = new Sql(dataSource)
        db.execute (query)
    }
}