hibernate/hibernate-orm · error · ObjectDeletedException
deleted object would be re-saved by cascade (remove deleted
Error message
deleted object would be re-saved by cascade (remove deleted object from associations)
What it means
When Hibernate must force a flush to push a deletion through (e.g. a subsequent operation needs the row gone), it calls forceFlush(EntityKey). If the session is currently mid-cascade, flushing would re-execute cascades and re-save the just-deleted entity, so Hibernate throws ObjectDeletedException('deleted object would be re-saved by cascade...'). The message names the classic cause: the deleted object is still referenced from an association that cascade-saves it.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java:1552
@Nonnull
public Set<EntityManager.Option> getOptions() {
return OptionsHelper.getOptions( this );
}
@Override
public void forceFlush(@Nonnull EntityEntry entityEntry) {
forceFlush( entityEntry.getEntityKey() );
}
@Override
public void forceFlush(@Nonnull EntityKey key) {
if ( SESSION_LOGGER.isTraceEnabled() ) {
SESSION_LOGGER.flushingToForceDeletion(
infoString( key.getPersister(), key.getIdentifier(), getFactory() ) );
}
if ( persistenceContext.getCascadeLevel() > 0 ) {
throw new ObjectDeletedException(
"deleted object would be re-saved by cascade (remove deleted object from associations)",
key.getIdentifier(),
key.getPersister().getEntityName()
);
}
checkOpenOrWaitingForAutoClose();
fireFlush();
}
/**
* give the interceptor an opportunity to override the default instantiation
*/
@Override
@Nonnull
public Object instantiate(@Nonnull EntityPersister persister, @Nullable Object id) {
checkOpenOrWaitingForAutoClose();
pulseTransactionCoordinator();
Object result = callInterceptorCallback(View on GitHub (pinned to fad1729dce)
Solutions
- Remove the entity from all owning associations before delete: parent.getChildren().remove(child); session.remove(child);
- Use orphanRemoval=true on the collection so removal from the collection implies deletion, avoiding manual remove of a still-referenced entity
- Check/adjust cascade settings: cascade=REMOVE or orphanRemoval instead of blanket cascade=ALL when children are managed through one side only
- Flush immediately after the delete (session.flush()) so later cascade work does not hit the pending deletion
Example fix
// before order.getItems().size(); // cascade=ALL on items session.remove(item); // still inside order.items session.remove(order); // forceFlush during cascade -> ObjectDeletedException // after order.getItems().remove(item); // sever association first session.remove(item); session.flush(); // deletion is now safely applied session.remove(order);
Defensive patterns
Strategy: try-catch
Validate before calling
// Sever associations before deleting, so cascade cannot re-save the entity parent.getChildren().remove(child); session.remove(child); session.flush(); // apply deletion before further cascade work
Try / catch
try {
session.remove(entity);
session.flush();
} catch (ObjectDeletedException e) {
// entity is still referenced by a cascade-persisting association
throw new IllegalStateException(
"Remove '" + e.getEntityName() + "' from its parent collection before deleting", e);
} Prevention
- Always remove the child from the parent collection before (or instead of) deleting it
- Prefer orphanRemoval=true so collection removal drives deletion through one path
- Avoid blanket cascade=ALL; declare exactly the cascade types each association needs
- Flush promptly after deletes so pending deletions do not collide with later cascades
When it happens
Trigger: session.remove(x) while x is still held in a cascade-persisting collection (e.g. parent.getChildren() still contains x with cascade=ALL), then any operation (delete of the parent, lock, query with auto-flush) triggers forceFlush while cascadeLevel > 0. Also bidirectional relations where the many-to-one side still points at the removed entity.
Common situations: Forgetting parent.getChildren().remove(child) before removing child; orphanRemoval=false with cascade=ALL; deleting a child then re-saving the parent in the same transaction; bulk re-save loops that walk collections containing soft-deleted items.
Related errors
- Cannot lazily initialize collection (collection is being rem
- Instance of '" + entityName + "' references an unsaved trans
- Instance of '%s' references an unsaved transient instance of
- many-to-one attribute [%s] specified delete-orphan but is no
- one-to-one attribute [%s] cannot specify orphan delete casca
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/fa2f0337082b9639.
Report an issue: GitHub.