hibernate/hibernate-orm · error · MappingException
one-to-one attribute [%s] cannot specify orphan delete casca
Error message
one-to-one attribute [%s] cannot specify orphan delete cascading as it is constrained
What it means
A <one-to-one> with constrained='true' stores its FK on this entity pointing at the referenced entity; the referenced row's lifecycle is bound to the owning row, so orphan-removal semantics are not applicable. Hibernate therefore rejects any cascade style containing delete-orphan on a constrained one-to-one at bind time, before the SessionFactory is built.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java:1905
if ( cascadeStyleName != null && cascadeStyleName.contains( "delete-orphan" )
&& !manyToOneBinding.isLogicalOneToOne() ) {
throw new MappingException(
"""
many-to-one attribute [%s] specified delete-orphan but is not specified as unique; \
remove delete-orphan cascading or specify unique="true"
"""
.formatted( manyToOneSource.getAttributeRole().getFullPath() ),
sourceDocument.getOrigin()
);
}
}
private static void checkConstrainedOneToOneOrphanDelete(
MappingDocument sourceDocument,
SingularAttributeSourceOneToOne oneToOneSource) {
final String cascadeStyleName = oneToOneSource.getCascadeStyleName();
if ( cascadeStyleName != null && cascadeStyleName.contains( "delete-orphan" ) ) {
throw new MappingException(
"one-to-one attribute [%s] cannot specify orphan delete cascading as it is constrained"
.formatted( oneToOneSource.getAttributeRole().getFullPath() ),
sourceDocument.getOrigin()
);
}
}
private void bindManyToOneAttribute(
final MappingDocument sourceDocument,
final SingularAttributeSourceManyToOne manyToOneSource,
ManyToOne manyToOneBinding,
String referencedEntityName) {
// NOTE: no type information to bind
handleReferencedEntity( manyToOneBinding, referencedEntityName,
manyToOneSource.getReferencedEntityAttributeName() );
handleFetchCharacteristics( manyToOneSource, manyToOneBinding );View on GitHub (pinned to fad1729dce)
Solutions
- Remove delete-orphan from the cascade of the constrained one-to-one
- If orphan-removal behavior is needed, put it on the owning (FK-holding, unconstrained) side of the association
- Note the constrained row is removed with its owner via the FK anyway, so cascade='delete' on the owner is usually sufficient
Example fix
// before <one-to-one name='employee' class='Employee' constrained='true' cascade='all-delete-orphan'/> // after <one-to-one name='employee' class='Employee' constrained='true' cascade='all'/>
Defensive patterns
Strategy: validation
Validate before calling
NodeList otos = doc.getElementsByTagName("one-to-one");
for (int i = 0; i < otos.getLength(); i++) {
Element o = (Element) otos.item(i);
if ("true".equals(o.getAttribute("constrained")) && o.getAttribute("cascade").contains("delete-orphan")) {
throw new IllegalStateException("constrained one-to-one " + o.getAttribute("name") + " cannot use delete-orphan");
}
} Try / catch
catch (MappingException e) during SessionFactory build; the message names the one-to-one attribute. Remove delete-orphan from that side's cascade and move orphan-removal semantics to the FK-owning side if needed.
Prevention
- Never put delete-orphan on the constrained side of a one-to-one
- Review cascade strings on both sides when making associations bidirectional
- Remember constrained rows are deleted through the FK with their owner anyway
When it happens
Trigger: <one-to-one name='...' constrained='true' cascade='delete-orphan'/> or cascade='all-delete-orphan' on the constrained side of a one-to-one association.
Common situations: Bidirectional one-to-one mappings where the same cascade string was copied to both sides; converting a many-to-one to one-to-one without adjusting the cascade; legacy Hibernate 3 mappings migrated forward.
Related errors
- many-to-one attribute [%s] specified delete-orphan but is no
- Cannot lazily initialize collection (collection is being rem
- deleted object would be re-saved by cascade (remove deleted
- Instance of '" + entityName + "' references an unsaved trans
- Instance of '%s' references an unsaved transient instance of
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/3695da12549ba516.
Report an issue: GitHub.