grails复合密钥更新
我有一个遗留数据库,我正在使用Grails。错误#1。grails复合密钥更新
它使用化合物密钥。错误#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,但外键指向人不被修改,如图:
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 ,目前它还没有角色,所以更新失败。
因此,短的只是删除旧角色并创建一个新的连接到期望的人,有什么办法解决?
答案是:
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)
}
}
尝试:
person1.removeFromRoles(角色)//角色是角色对象从哪个人要被移除
role.person = PERSON2
应该工作。
谢谢,好主意,但电脑说“不(咳嗽)”。我实现了你的想法,这个想法在正确的方向上似乎正在取得进展,因为突然间我得到了ConcurrentModificationException,因为我在迭代它时正在修改角色列表。但是,一旦我改变了我的代码遍历表的副本,它仍然在完全相同:-(以同样的方式在一个理想的世界中发生故障时,“应努力”是可行的。 – 2012-08-15 19:23:36
所以你刚才添加的'addToRoles'代码。 。我的回答值得一给予好评:P – 2012-08-16 05:07:36
当然,你应得的给予好评感谢您的帮助,但我没有足够的代表 - #1不会让我 但是,没有,addToRoles也不是办法的!。这个解决方案的灵魂是原始的SQL更新,GORM完全无法对底层表做任何事情,这是几乎可以理解的,因为我们永远不应该改变主键,组合或其他方式,愚蠢的遗留数据库addToRoles只是确保Grails对数据库的新状态有一个准确的描述。 – 2012-08-25 09:01:02
于是,我放弃了对更新的方法,并试图删除旧/插入新的,但是,即使是失败了。 GORM不会让我oldRole.delete(),因为它仍然与oldPerson有关联。我不能oldPerson.removeFromRoles(oldRole); oldRole.delete()因为在那时,oldRole.person == null,并且Hibernate试图从TABLE中删除person_id = null,并且失败。我无法逆转订单,因为“删除行将在保存级联期间被重新创建”。 有血的砖墙,我一直在敲打我的头下的地板上的池,而墙的名字是GORM。 – 2012-08-15 22:22:08