Gen*_*sky 3 grails grails-orm cascading-deletes
我使用的是Grails 1.3.7,并具有以下域类:
package com.fxpal.test
class UserGroup {
String name
static constraints = {
name(blank: false)
}
}
class Invitation {
UserGroup group
String user
static belongsTo = [group: UserGroup]
static constraints = {
group(nullable: false)
}
}
Run Code Online (Sandbox Code Playgroud)
我希望能够删除在删除该UserGroup实例时引用UserGroup实例的所有Invitation实例,而没有引用UserGroup中的Invitation的显式关系.换句话说,我想从UserGroup到Invitation进行级联删除,而不修改Group.
由于表示邀请 - > UserGroup关系的约束,我对此测试失败:
void testCascadingDelete() {
UserGroup group1 = new UserGroup(name: 'group1').save(flush: true, failOnError: true)
UserGroup group2 = new UserGroup(name: 'group2').save(flush: true, failOnError: true)
Invitation invitation = new Invitation(user:'user1', group: group1).save(flush: true, failOnError: true)
assertEquals("Wrong number of groups.", 2, UserGroup.count())
assertEquals("Wrong number of invitations.", 1, Invitation.count())
group1.delete(flush: true, failOnError: true)
assertEquals("Wrong number of groups.", 1, UserGroup.count())
assertEquals("Wrong number of invitations.", 0, Invitation.count())
}
Run Code Online (Sandbox Code Playgroud)
当我运行测试时,它会像这样失败:
could not delete: [com.fxpal.test.UserGroup#1]; SQL [delete from user_group where id=? and version=?]; constraint [FK473F7799A8642225]; nested exception is org.hibernate.exception.ConstraintViolationException: could not delete: [com.fxpal.test.UserGroup#1]
org.springframework.dao.DataIntegrityViolationException: could not delete: [com.fxpal.test.UserGroup#1]; SQL [delete from user_group where id=? and version=?]; constraint [FK473F7799A8642225]; nested exception is org.hibernate.exception.ConstraintViolationException: could not delete: [com.fxpal.test.UserGroup#1]
at com.fxpal.test.InvitationIntegrationTests.testCascadingDelete(InvitationIntegrationTests.groovy:23)
Caused by: org.hibernate.exception.ConstraintViolationException: could not delete: [com.fxpal.test.UserGroup#1]
at com.fxpal.test.InvitationIntegrationTests.testCascadingDelete(InvitationIntegrationTests.groovy:23)
...
Run Code Online (Sandbox Code Playgroud)
它似乎是规范的鼻子面部示例,但级联删除似乎不起作用.我真的不想在UserGroup中代表邀请,特别是因为最后,邀请将引用其他几个域类,删除其中任何一个类都会导致相应的邀请被删除.
我错过了什么?
基因
我不确定在没有双向关系的情况下是否可行,但您可以在事务服务方法中轻松完成(以确保删除所有操作或不发生):
void deleteGroup(UserGroup group) {
Invitation.executeUpdate(
'delete from Invitation where group=:group',
[group: group])
group.delete(flush: true, failOnError: true)
}
Run Code Online (Sandbox Code Playgroud)
然后你的测试就变成了
def fooService
...
void testCascadingDelete() {
UserGroup group1 = new UserGroup(name: 'group1').save(flush: true, failOnError: true)
UserGroup group2 = new UserGroup(name: 'group2').save(flush: true, failOnError: true)
Invitation invitation = new Invitation(user:'user1', group: group1).save(flush: true, failOnError: true)
assertEquals("Wrong number of groups.", 2, UserGroup.count())
assertEquals("Wrong number of invitations.", 1, Invitation.count())
fooService.deleteGroup group1
assertEquals("Wrong number of groups.", 1, UserGroup.count())
assertEquals("Wrong number of invitations.", 0, Invitation.count())
}
Run Code Online (Sandbox Code Playgroud)
一些小的不相关的注释 - 默认情况下属性不为null,因此您可以删除group(nullable: false)约束.而一个belongsTo在地图的形式像你这样定义名称的变量,因此可以省略UserGroup group的Invitation.
更新:
另一个不太干扰的选项是在以下位置使用before-delete事件UserGroup:
def beforeDelete() {
Invitation.executeUpdate(
'delete from Invitation where group=:group',
[group: this])
}
Run Code Online (Sandbox Code Playgroud)