{"record":{"id":"7264060c5667172b","repo":"hibernate/hibernate-orm","slug":"expecting-dml-target-entity-type-s-but-got-s","errorCode":null,"errorMessage":"Expecting DML target entity type [%s] but got [%s]","messagePattern":"Expecting DML target entity type \\[(.+?)\\] but got \\[(.+?)\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/AbstractSqmRestrictedDmlStatement.java","lineNumber":78,"sourceCode":"\tprotected @Nullable SqmWhereClause copyWhereClause(SqmCopyContext context) {\n\t\tif ( whereClause == null ) {\n\t\t\treturn null;\n\t\t}\n\t\telse {\n\t\t\tfinal var predicate = whereClause.getPredicate();\n\t\t\treturn new SqmWhereClause( predicate == null ? null : predicate.copy( context ), nodeBuilder() );\n\t\t}\n\t}\n\n\tpublic SqmRoot<T> from(Class<T> entityClass) {\n\t\treturn from( nodeBuilder().getDomainModel().entity( entityClass ) );\n\t}\n\n\tpublic SqmRoot<T> from(EntityType<T> entity) {\n\t\tfinal var entityDomainType = (EntityDomainType<T>) entity;\n\t\tfinal var root = getTarget();\n\t\tif ( root.getModel() != entity ) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\"Expecting DML target entity type [%s] but got [%s]\",\n\t\t\t\t\t\t\troot.getModel().getHibernateEntityName(),\n\t\t\t\t\t\t\tentityDomainType.getName()\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t\treturn root;\n\t}\n\n\tpublic SqmRoot<T> getRoot() {\n\t\treturn getTarget();\n\t}\n\n\tpublic @Nullable SqmWhereClause getWhereClause() {\n\t\treturn whereClause;\n\t}\n","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/AbstractSqmRestrictedDmlStatement.java#L60-L96","documentation":"AbstractSqmRestrictedDmlStatement.from(EntityType) requires the passed EntityType to be the exact model of the DML target root (root.getModel() != entity is a reference comparison). Criteria insert/update/delete statements operate on exactly one entity, so from() only hands back the existing target root; passing any other entity type throws IllegalArgumentException showing the expected and the received entity names.","triggerScenarios":"cb.createCriteriaUpdate(Person.class) followed by update.from(Employee.class) or update.from(otherMetamodel.entity(Person.class)); from(Class) resolving to a different entity than the one used in createCriteriaUpdate/createCriteriaDelete/createCriteriaInsertSelect.","commonSituations":"Copy-pasting a select-query pattern (where from() may be called with any entity) into a DML builder; generic DML helpers that take target and filter entities separately; two SessionFactories in tests supplying EntityType instances from different metamodels (reference inequality).","solutions":["Call from() with the same class/entity you passed to createCriteriaUpdate/Delete/InsertSelect.","Skip from() entirely: use getRoot() / getTarget() on the DML statement to obtain the root.","In generic code, carry a single Class<E> parameter and use it for both statement creation and from()."],"exampleFix":"// before\nCriteriaUpdate<Employee> update = cb.createCriteriaUpdate( Employee.class );\nRoot<Person> root = update.from( Person.class ); // throws\n// after\nRoot<Employee> root = update.from( Employee.class ); // or update.getRoot()","handlingStrategy":"validation","validationCode":"// before calling from():\nEntityType<T> expected = (EntityType<T>) update.getRoot().getModel();\nif ( expected != entity ) {\n    throw new IllegalArgumentException(\n        \"DML target is \" + expected.getName() + \", refusing from(\" + entity.getName() + \")\" );\n}\nRoot<T> root = update.from( entity );","typeGuard":"static boolean isDmlTarget(AbstractSqmDmlStatement<?> dml, EntityType<?> candidate) {\n    return dml.getRoot().getModel() == candidate; // reference equality, same as the check\n}","tryCatchPattern":"try {\n    root = update.from( entity );\n} catch (IllegalArgumentException e) {\n    if ( e.getMessage() != null && e.getMessage().startsWith( \"Expecting DML target entity type\" ) ) {\n        root = update.getRoot(); // fall back to the real target root\n    } else { throw e; }\n}","preventionTips":["In generic DML code, derive the root with getRoot()/getTarget() instead of from().","Create the statement and its from() from one Class<E> variable.","Remember the check is by reference: use EntityType objects from the same SessionFactory/metamodel."],"tags":["hibernate","criteria-api","dml","entity-mismatch","illegal-argument"],"backgroundTag":"entity-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}