Entity transient because soft-deleted?

Hey guys!

We have the following case (Hibernate 6.6.11.Final, WildFly 35, JPA):

@Entity
@SQLDelete("UPDATE A SET DELETED = 1 WHERE ID=? AND ROW_VERSION=?", verify = Expectation.RowCount.class)
public class A {
    @Id
    private Long id;

    @ManyToOne
    @JoinColumn("B1_ID")
    private B b1;

    @ManyToOne
    @JoinColumn("B2_ID")
    private B b2;

    @Column("DELETED")
    private boolean deleted;

    @Version
    @Column(name = "ROW_VERSION")
    private int rowVersion;
}

@Entity
public class B {
    @Id
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "A_ID", referencedColumnName = "ID")
    private A a;

    @Column(name = "DELETE_DATE")
    @Temporal(TemporalType.TIMESTAMP)
    private Date deleteDate;

    @Version
    @Column(name = "ROW_VERSION")
    private int rowVersion;
}

What happens now is the following:

  1. We merge entity A. This also attaches entities b1 and b2 to the persistence context.
  2. We remove entity B.
  3. When the transaction is flushed, we get a TransientObjectException for B#a, because CascadingActions#isChildTransient returns true because of entry.getStatus().isDeletedOrGone().

In our thinking, it’s valid that B still references the deleted A because it was not really deleted. The deleted A can also be found later, because it still exists in the DB. So should CascadingActions#isChildTransient consider that the entity was only soft-deleted and not say that it is transient?

What do you guys think? Thanks in advance!

Hi, this is an interesting edge case that probably also affects the built-in soft-delete of Hibernate ORM 7+ and is hard to give a good answer here. I guess there will be lots of opinions.

I would suggest you start a discussion on our chat platform Zulip.

1 Like