Sleeping circular foreign key

I need to check a code that I have not written myself. This is an integration test: the application runs constantly on the server, and my tests work against it.

Testing - these are Selenium tests, they launch the browser, execute JavaScript inside it to simulate user actions and checks if the database is updated correctly. I have to restore the database to its original state after each.

For this, I use Spring and Hibernate annotations through the DAO, I myself have not written.

The problem is that there are circular foreign keys. An object of class A has a OneToMany relationship with objects of type B, and there is also an association of ManyToOne with the same class. I am trying to delete an object of type A and all its related B in the same transaction, but it does not work , because Hibernate tries to set the value of "defaultB" to null before deleting an object of type A . It is completely optional to nullify it, although it makes sense to do so as soon as a deleted object of type B is deleted.

I (naively) believed that, since 2 operations were performed in the same transaction, deleting an object β€œa” of type A that references (and referencing) an object β€œb” of class B and deleting b at the same time will not a problem. However, I was wrong. Is this a way to do this without changing the DB model (which I haven't written yet)?

Update 1 . I don’t understand why, when I execute mySession.delete (B), Hibernate tries to collapse the key that it knows is invalid ... any thoughts on this?

2: " " C B. "c_id" , B, C, c_id. , 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;
    }

}
+3
2

A B

REMOVE , Bs . ( 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;
    }
}

. BTW, B , , Hibernate , .

... , . ( A):

public removeFromBs(B b) {
    b.setA(null);
    this.getBs().remove(b);
}
+2

, a, Hibernate , b ?

, "" b a a. , b.setA(null) .

0

Source: https://habr.com/ru/post/1760338/


All Articles