{"record":{"id":"4f5b26fadc19a828","repo":"hibernate/hibernate-orm","slug":"target-type-s-is-not-an-entity-4f5b26","errorCode":null,"errorMessage":"Target type '%s' is not an entity","messagePattern":"Target type '(.+?)' is not an entity","errorType":"exception","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/update/SqmUpdateStatement.java","lineNumber":272,"sourceCode":"\t\treturn versioned;\n\t}\n\n\t@Override\n\tpublic SqmUpdateStatement<T> versioned() {\n\t\tthis.versioned = true;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic SqmUpdateStatement<T> versioned(boolean versioned) {\n\t\tthis.versioned = versioned;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void setTarget(@Nonnull JpaRoot<T> root) {\n\t\tif ( root.getModel() instanceof SqmPolymorphicRootDescriptor<?> ) {\n\t\t\tthrow new SemanticException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\"Target type '%s' is not an entity\",\n\t\t\t\t\t\t\troot.getModel().getHibernateEntityName()\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t\tsuper.setTarget( root );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmUpdateStatement<T> where(@Nonnull Expression<Boolean> restriction) {\n\t\tsetWhere( restriction );\n\t\treturn this;\n\t}\n\n\t@Nonnull\n\t@Override","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/update/SqmUpdateStatement.java#L254-L290","documentation":"When you set the target of a criteria UPDATE, SqmUpdateStatement.setTarget rejects roots whose model is an SqmPolymorphicRootDescriptor — Hibernate's synthetic type that stands for 'several entities at once' (e.g., a MappedSuperclass/abstract hierarchy root or an explicit polymorphic reference). There is no single entity to update in that case, so a SemanticException 'Target type ... is not an entity' is thrown.","triggerScenarios":"cb.createCriteriaUpdate(AbstractSuperclass.class) where AbstractSuperclass is a @MappedSuperclass (or polymorphic-typed root), then setTarget(root) — or building the update directly from a root of a non-entity abstract type.","commonSituations":"Inheritance hierarchies where services are typed against the abstract base; generic update helpers parameterized on a base class; code migrated from HQL updates on superclasses, which have their own restrictions.","solutions":["Target a concrete @Entity subtype in createCriteriaUpdate(...) and in the root you pass to setTarget(...)","If all subtypes need updating, iterate the concrete subtypes (from metamodel.getEntities() or your known list) and execute one update per entity","Reconsider the design: polymorphic bulk updates across unioned entity tables are not expressible as a single SQL statement anyway"],"exampleFix":"// before\n@MappedSuperclass abstract class BaseEvent { ... }\nCriteriaUpdate<BaseEvent> u = cb.createCriteriaUpdate(BaseEvent.class); // polymorphic root\nu.setTarget(u.from(BaseEvent.class)); // SemanticException: Target type is not an entity\n\n// after — one update per concrete entity\nfor (Class<?> concrete : List.of(LoginEvent.class, PurchaseEvent.class)) {\n    @SuppressWarnings(\"unchecked\")\n    CriteriaUpdate<BaseEvent> u = (CriteriaUpdate<BaseEvent>) cb.createCriteriaUpdate(concrete);\n    Root<BaseEvent> r = (Root<BaseEvent>) u.from(concrete);\n    u.set(r.get(\"archived\"), true);\n    em.createQuery(u).executeUpdate();\n}","handlingStrategy":"validation","validationCode":"if (AbstractSuperclass.class.isAssignableFrom(targetType) && !targetType.isAnnotationPresent(jakarta.persistence.Entity.class)) {\n    throw new IllegalArgumentException(\"Update target must be a concrete @Entity, got \" + targetType);\n}","typeGuard":"static boolean isConcreteEntity(Class<?> c) { return c.isAnnotationPresent(jakarta.persistence.Entity.class); }","tryCatchPattern":"try { update.setTarget(root); } catch (SemanticException e) { if (e.getMessage().contains(\"not an entity\")) { /* rebuild update against a concrete subtype */ } else throw e; }","preventionTips":["Type generic update services by concrete entity classes, constrain generics with @Entity-typed parameters","Validate the target is annotated @Entity before building a CriteriaUpdate","For hierarchies, keep an explicit list of concrete subtypes and loop over it for bulk updates"],"tags":["hibernate","criteria-api","inheritance","polymorphism","bulk-update"],"backgroundTag":"polymorphic-update-target","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}