java - hibernate 循环外键

标签 java hibernate spring orm

我必须测试一些不是我自己写的代码。这是一个集成测试:应用程序在服务器上持续运行,我的测试针对它运行。

测试是 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/

相关文章:

java - hibernate : merge an object detached from the session

java - Grails 获取原始 Controller 的 url

java - Spring Boot Security XML 与 CSRF 的 WebSecurityConfigurerAdapter

java - JAR 文件中的 Liquibase 变更集

java - NetLogo HPC 内存错误

java - LWJGL - 加载字体后一切都消失了

java - 是否可以通过 DB 或 Rest 通过任务列表使 Camunda Webapps(Spring-boot 独立)更新 .bpmn

java - 如何在不关闭 OutputStream 对象的情况下强制刷新它?

java - Hibernate 外键约束失败

spring - 是否有任何嵌入式数据库支持 JSON 数据类型?