{"record":{"id":"3695da12549ba516","repo":"hibernate/hibernate-orm","slug":"one-to-one-attribute-s-cannot-specify-orphan-de","errorCode":null,"errorMessage":"one-to-one attribute [%s] cannot specify orphan delete cascading as it is constrained","messagePattern":"one-to-one attribute \\[(.+?)\\] cannot specify orphan delete cascading as it is constrained","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java","lineNumber":1905,"sourceCode":"\t\tif ( cascadeStyleName != null && cascadeStyleName.contains( \"delete-orphan\" )\n\t\t\t\t&& !manyToOneBinding.isLogicalOneToOne() ) {\n\t\t\tthrow new MappingException(\n\t\t\t\t\t\"\"\"\n\t\t\t\t\tmany-to-one attribute [%s] specified delete-orphan but is not specified as unique; \\\n\t\t\t\t\tremove delete-orphan cascading or specify unique=\"true\"\n\t\t\t\t\t\"\"\"\n\t\t\t\t\t\t\t.formatted( manyToOneSource.getAttributeRole().getFullPath() ),\n\t\t\t\t\tsourceDocument.getOrigin()\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate static void checkConstrainedOneToOneOrphanDelete(\n\t\t\tMappingDocument sourceDocument,\n\t\t\tSingularAttributeSourceOneToOne oneToOneSource) {\n\t\tfinal String cascadeStyleName = oneToOneSource.getCascadeStyleName();\n\t\tif ( cascadeStyleName != null && cascadeStyleName.contains( \"delete-orphan\" ) ) {\n\t\t\tthrow new MappingException(\n\t\t\t\t\t\"one-to-one attribute [%s] cannot specify orphan delete cascading as it is constrained\"\n\t\t\t\t\t\t\t.formatted( oneToOneSource.getAttributeRole().getFullPath() ),\n\t\t\t\t\tsourceDocument.getOrigin()\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate void bindManyToOneAttribute(\n\t\t\tfinal MappingDocument sourceDocument,\n\t\t\tfinal SingularAttributeSourceManyToOne manyToOneSource,\n\t\t\tManyToOne manyToOneBinding,\n\t\t\tString referencedEntityName) {\n\t\t// NOTE: no type information to bind\n\n\t\thandleReferencedEntity( manyToOneBinding, referencedEntityName,\n\t\t\t\tmanyToOneSource.getReferencedEntityAttributeName() );\n\n\t\thandleFetchCharacteristics( manyToOneSource, manyToOneBinding );","sourceCodeStart":1887,"sourceCodeEnd":1923,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java#L1887-L1923","documentation":"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.","triggerScenarios":"<one-to-one name='...' constrained='true' cascade='delete-orphan'/> or cascade='all-delete-orphan' on the constrained side of a one-to-one association.","commonSituations":"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.","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"],"exampleFix":"// before\n<one-to-one name='employee' class='Employee' constrained='true' cascade='all-delete-orphan'/>\n\n// after\n<one-to-one name='employee' class='Employee' constrained='true' cascade='all'/>","handlingStrategy":"validation","validationCode":"NodeList otos = doc.getElementsByTagName(\"one-to-one\");\nfor (int i = 0; i < otos.getLength(); i++) {\n    Element o = (Element) otos.item(i);\n    if (\"true\".equals(o.getAttribute(\"constrained\")) && o.getAttribute(\"cascade\").contains(\"delete-orphan\")) {\n        throw new IllegalStateException(\"constrained one-to-one \" + o.getAttribute(\"name\") + \" cannot use delete-orphan\");\n    }\n}","typeGuard":null,"tryCatchPattern":"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.","preventionTips":["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"],"tags":["hibernate","hbm-mapping","cascade","one-to-one","orphan-removal"],"backgroundTag":"delete-orphan-cascade-misuse","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}