我必须测试一些不是我自己写的代码。这是一个集成测试:应用程序在服务器上持续运行,我的测试针对它运行。
测试是 Selenium 测试,它们启动浏览器,在其中执行一些 JavaScript 以模拟用户操作并检查数据库是否正确更新。我必须在每次之后将数据库恢复到其初始状态。
为此,我通过非我自己编写的 DAO 使用 Spring 注释和 Hibernate。
问题是有循环外键。类A的对象与类B的对象是一对多的关系,同一个类也存在多对一的关系。我尝试在同一事务中删除 A 类型的对象及其所有关联的 B,但它不起作用因为 Hibernate 在删除 A 类型的对象之前尝试将“defaultB”设置为 null。完全没有必要取消它,尽管在删除类型 B 的引用对象后这样做是有意义的。
我(天真地)认为因为这2个操作是在同一个事务中执行的,删除引用(并被引用)类B的对象“b”的类型A的对象“a”并同时删除b时间不会有问题。然而,我完全错了。有没有办法做到这一点无需更改数据库模型(我没有写过)?
更新 1:我不明白为什么当我执行 mySession.delete(B) 时,Hibernate 会尝试使它知道不可为 null 的键无效……对此有什么想法吗?
更新2:C类到B类是一对多的关系。当我删除具有此 c_id 的 C 对象。而且即使我在其“父”之前删除了 B 类的对象。我知道 Hibernate 会重新排序查询并添加一些它自己的东西,但我不明白重新排序已经处于正确顺序的查询以使它们失败的意义。
以下是类(的相关部分):
@Entity
@Table(name = "A")
public class A {
private Set<B> bs;
private B defaultB;
@OneToMany(mappedBy = "a", fetch = LAZY)
public Set<B> getBs() {
return bs;
}
public void setBs(Set<B> bs) {
this.bs = bs;
}
@ManyToOne(fetch = LAZY, optional = false)
@JoinColumn(name = "default_b_id", nullable = false)
public B getDefaultB(){
return defaultB;
}
public void setDefaultB(B defaultB) {
this.defaultB = defaultB;
}
}
@Entity
@Table(name = "B")
public class B {
private a;
@ManyToOne(fetch = LAZY, optional = false)
@JoinColumn(name = "A_id", nullable = false)
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
最佳答案
I try to delete an object of type A and all its associated B's in the same transaction
如果您不想手动删除所有 B,您应该为此级联 REMOVE
操作。我会尝试以下操作(在两个关联上使用 cascade
):
@Entity
@Table(name = "A")
public class A {
private Set<B> bs;
private B defaultB;
@OneToMany(mappedBy = "a", fetch = LAZY, cascade=CascadeType.REMOVE)
public Set<B> getBs() {
return bs;
}
public void setBs(Set<B> bs) {
this.bs = bs;
}
@ManyToOne(fetch = LAZY, optional = false, cascade=CascadeType.REMOVE)
@JoinColumn(name = "default_b_id", nullable = false)
public Strategy getDefaultB(){
return defaultB;
}
public void setDefaultB(B defaultB) {
this.defaultB = defaultB;
}
}
I cannot change these annotations. BTW, I do remove all associated B's manually, it's just that the queries Hibernate issues don't do what I want.
好吧...但是我猜你在删除实体之前没有正确更新双向关联的双方。这通常是在像这样的防御性编程方法中完成的(在 A
中):
public removeFromBs(B b) {
b.setA(null);
this.getBs().remove(b);
}
关于java - hibernate 循环外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3513950/