{"record":{"id":"3a463cd53fa55f3f","repo":"hibernate/hibernate-orm","slug":"any-types-do-not-have-a-unique-referenced-persiste","errorCode":null,"errorMessage":"any types do not have a unique referenced persister","messagePattern":"any types do not have a unique referenced persister","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/AnyType.java","lineNumber":515,"sourceCode":"\t}\n\n\tpublic boolean isReferenceToPrimaryKey() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String getRHSUniqueKeyPropertyName() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean isAlwaysDirtyChecked() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic Joinable getAssociatedJoinable(SessionFactoryImplementor factory) {\n\t\tthrow new UnsupportedOperationException(\"any types do not have a unique referenced persister\");\n\t}\n\n\t@Override\n\tpublic String getAssociatedEntityName(SessionFactoryImplementor factory) {\n\t\tthrow new UnsupportedOperationException(\"any types do not have a unique referenced persister\");\n\t}\n\n\t/**\n\t * Used to externalize discrimination per a given identifier.  For example, when writing to\n\t * second level cache we write the discrimination resolved concrete type for each entity written.\n\t */\n\tpublic static final class ObjectTypeCacheEntry implements Serializable {\n\t\tfinal String entityName;\n\t\tfinal Object id;\n\n\t\tObjectTypeCacheEntry(String entityName, Object id) {\n\t\t\tthis.entityName = entityName;\n\t\t\tthis.id = id;","sourceCodeStart":497,"sourceCodeEnd":533,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/AnyType.java#L497-L533","documentation":"AnyType implements AssociationType but cannot honor getAssociatedJoinable, because an @Any reference points at many possible entity persisters depending on the discriminator value, so there is no single Joinable to resolve. AnyType.getAssociatedJoinable (AnyType.java:514) therefore throws UnsupportedOperationException whenever the query/AST machinery asks for the joinable behind an any-typed association.","triggerScenarios":"HQL or Criteria that (implicitly or explicitly) JOINs across an @Any/@ManyToAny attribute, e.g. 'select d from Doc d join d.owner o where o.status = :s'; fetch-joining an @Any; ORDER BY / GROUP BY a nested path that forces an implicit join; programmatic calls to getAssociatedJoinable on the type of an any-mapped property.","commonSituations":"Teams migrating queries written for @ManyToOne after switching the mapping to @Any for polymorphism; generic query builders / specifications that join every referenced path; Envers or reporting tools walking associations uniformly and expecting a single target persister.","solutions":["Remove joins over the @Any attribute; filter with its 'class' and 'id' sub-attributes and resolve targets with a second query or batch load.","Replace @Any with real associations: one @ManyToOne per target type, or an intermediate link entity (table per relationship with discriminator + real FK) that can be joined.","For @ManyToAny collections, iterate elements and operate on the concrete types instead of joining the collection in HQL.","If you control the generic query layer, exclude any-typed attributes from automatic join generation."],"exampleFix":"// before\nList<Doc> docs = session.createQuery(\n    \"select d from Doc d join d.owner o where o.status = :s\", Doc.class)\n    .setParameter(\"s\", Status.ACTIVE).getResultList();\n\n// after: no join across @Any; two-step resolution\nList<Doc> docs = session.createQuery(\n    \"select d from Doc d where d.owner.class = User and d.owner.id in :ids\", Doc.class)\n    .setParameter(\"ids\", activeUserIds).getResultList();","handlingStrategy":"type-guard","validationCode":"// Before building joins generically, skip any-typed associations\nType t = persister.getPropertyType(propName);\nif (t instanceof org.hibernate.type.AnyType) {\n    // no joinable exists: filter via class/id or restructure the mapping\n    continue;\n}","typeGuard":"static boolean isJoinableAssociation(Type t) {\n    return t instanceof AssociationType && !(t instanceof org.hibernate.type.AnyType);\n}","tryCatchPattern":"try {\n    return session.createQuery(\"select d from Doc d join d.owner o\", Doc.class).getResultList();\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage().contains(\"unique referenced persister\")) {\n        throw new QueryDesignException(\n            \"Cannot join across @Any attribute 'owner'; query via class+id instead\", e);\n    }\n    throw e;\n}","preventionTips":["Ban joins (explicit or implicit) over @Any/@ManyToAny attributes in query-review checklists.","If joins are a hard requirement, model the polymorphic link with a real association entity instead of @Any.","Lint generated queries for navigation paths that cross any-typed attributes."],"tags":["hibernate","any-mapping","join","hql","association"],"backgroundTag":"unsupported-polymorphic-join","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}