Home > Back-end >  CascadeType.ALL without CascadeType.REMOVE changes persist behavior
CascadeType.ALL without CascadeType.REMOVE changes persist behavior

Time:11-16

In this project I have two Entities A and B that each have a OneToOne relationship to Entity C. There are some C that are referenced by A and B.

@Entity
public class A {
    @NotNull
    @OneToOne(cascade = { CascadeType.ALL })
    @JoinColumn(name = "fk_c", foreignKey = @ForeignKey(name = "fk_a_2_c"))
    private C c;
}

@Entity
public class B {
    @NotNull
    @OneToOne(cascade = { CascadeType.ALL })
    @JoinColumn(name = "fk_c", foreignKey = @ForeignKey(name = "fk_b_2_c"))
    private C c;
}

@Entity
public class C {
    @Nullable
    @OneToOne(mappedBy = "c", fetch = FetchType.LAZY)
    private A a;

    @Nullable
    @OneToOne(mappedBy = "c", fetch = FetchType.LAZY)
    private B b;
}

Until now everything was working fine using CascadeType.ALL on field c in Entity B. We now want to delete Entity B without ever deleting Entity C. Thus, we change the cascading in Entity B to

@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })

Now, the delete behavior is as desired, but when persisting Entity B there is no persist cascading for Entity C, instead we get an org.springframework.dao.InvalidDataAccessApiUsageException

Not-null property references a transient value - transient instance must be saved before current operation : xxx.B.c -> xxx.C

I already tried placing all cascade types (PERSIST, MERGE, REMOVE, REFRESH, DETACH) which, according to the javax.persistence documentation should yield the same result as CascadeType.ALL. The error stated above still occurs.

So: How can I keep the cascading behavior of CascadeType.ALL without REMOVE-cascading?

CodePudding user response:

In an older question/answer Hibernate: CasecadeType.ALL vs {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH, CascadeType.REMOVE} I learned that the CascadeType enum of javax.persistence does not work properly when using hibernates save/saveOrUpdate.

Using session.persist instead of session.saveOrUpdate was not desirable in my case, so I needed to change the cascading on my entity from

@OneToOne(cascade = CascadeType.ALL)

to

@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
@OneToOne

Now saving and deleting both work just fine.

  • Related