I have following entities with @OneToOne relation:
@Entity
public static class EntityChild extends BaseEntity {
//Id from superclass
}
@Entity
public static class EntityParent extends BaseEntity {
//Id from superclass
@OneToOne(cascade = ALL)
private EntityChild child;
//child getter/setter
}
Now following test doesn't pass:
EntityParent parent = new EntityParent();
em.persist(parent);
em.flush();
EntityChild child = new EntityChild();
parent.setChild(child);
em.persist(parent);
em.flush();
em.remove(parent.getChild());
em.flush();
It throws exception on the last line, with flush(). The exception is javax.persistence.EntityNotFoundException: deleted entity passed to persist: [my.package.EntityChild#<null>]
Why can't I delete this entity?
You need to remove the association between parent and child first, otherwise Hibernate tries to persist the child again due to cascade = ALL
:
EntityChild c = parent.getChild();
parent.setChild(null);
em.remove(c);
em.flush();
Update:
Here are excerpts from the JPA specification related to this behaviour. Exception is thrown due to conflict between [1] and [2] during flush()
(though I can't find where it's specified):
The semantics of the flush operation, applied to an entity X are as follows:
If X is a managed entity, it is synchronized to the database.
For all entities Y referenced by a relationship from X, if the relationship to Y has been annotated with the
cascade
element valuecascade=PERSIST
orcascade=ALL
, the persist operation is applied to Y.For any entity Y referenced by a relationship from X, where the relationship to Y has not been annotated with the
cascade
element valuecascade=PERSIST
orcascade= ALL
:
If Y is new or removed, an
IllegalStateException
will be thrown by the flush operation (and the transaction marked for rollback) or the transaction commit will fail.If Y is detached, the semantics depend upon the ownership of the relationship. If X owns the relationship, any changes to the relationship are synchronized with the database; otherwise, if Y owns the relationships, the behavior is undefined.
If X is a removed entity, it is removed from the database. No cascade options are relevant. <--------------- [1]
The semantics of the persist operation, applied to an entity X are as follows:
If X is a new entity, it becomes managed. The entity X will be entered into the database at or before transaction commit or as a result of the flush operation.
If X is a preexisting managed entity, it is ignored by the persist operation. However, the persist operation is cascaded to entities referenced by X, if the relationships from X to these other entities are annotated with the
cascade=PERSIST
orcascade=ALL
annotation element value or specified with the equivalent XML descriptor element.If X is a removed entity, it becomes managed. <--------------- [2]
If X is a detached object, the
EntityExistsException
may be thrown when the persist operation is invoked, or theEntityExistsException
or anotherPersistenceException
may be thrown at flush or commit time.For all entities Y referenced by a relationship from X, if the relationship to Y has been annotated with the cascade element value
cascade=PERSIST
orcascade=ALL
, the persist operation is applied to Y.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With