{"record":{"id":"7688e1eb4b8fec7c","repo":"hibernate/hibernate-orm","slug":"only-embeddables-without-collections-are-supported","errorCode":null,"errorMessage":"Only embeddables without collections are supported!","messagePattern":"Only embeddables without collections are supported!","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tuple/internal/AnonymousTupleEmbeddableValuedModelPart.java","lineNumber":123,"sourceCode":"\t\tthis.domainType = domainType;\n\t\tthis.componentName = componentName;\n\t\tthis.existingModelPartContainer = existingModelPartContainer;\n\t\tthis.fetchableIndex = fetchableIndex;\n\t}\n\n\tprivate Map<String, ModelPart> createModelParts(\n\t\t\tSqmExpressible<?> sqmExpressible,\n\t\t\tSqlTypedMapping[] sqlTypedMappings,\n\t\t\tint selectionIndex,\n\t\t\tString selectionExpression,\n\t\t\tSet<String> compatibleTableExpressions,\n\t\t\tSet<? extends Attribute<?, ?>> attributes,\n\t\t\tEmbeddableValuedModelPart modelPartContainer) {\n\t\tfinal Map<String, ModelPart> modelParts = CollectionHelper.linkedMapOfSize( attributes.size() );\n\t\tint index = 0;\n\t\tfor ( Attribute<?, ?> attribute : attributes ) {\n\t\t\tif ( !( attribute instanceof SingularPersistentAttribute<?, ?> ) ) {\n\t\t\t\tthrow new IllegalArgumentException( \"Only embeddables without collections are supported!\" );\n\t\t\t}\n\t\t\tfinal DomainType<?> attributeType = ( (SingularPersistentAttribute<?, ?>) attribute ).getType();\n\t\t\tfinal ModelPart modelPart = AnonymousTupleTableGroupProducer.createModelPart(\n\t\t\t\t\tthis,\n\t\t\t\t\tsqmExpressible,\n\t\t\t\t\tattributeType,\n\t\t\t\t\tsqlTypedMappings,\n\t\t\t\t\tselectionIndex + index,\n\t\t\t\t\tselectionExpression + \"_\" + attribute.getName(),\n\t\t\t\t\tattribute.getName(),\n\t\t\t\t\tmodelPartContainer.findSubPart( attribute.getName(), null ),\n\t\t\t\t\tcompatibleTableExpressions,\n\t\t\t\t\tindex++\n\t\t\t);\n\t\t\tmodelParts.put( modelPart.getPartName(), modelPart );\n\t\t}\n\t\treturn modelParts;\n\t}","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tuple/internal/AnonymousTupleEmbeddableValuedModelPart.java#L105-L141","documentation":"When a dynamic instantiation / tuple selection (select new, criteria tuple/array) is reused as an embeddable-valued model part, Hibernate builds an AnonymousTupleEmbeddableValuedModelPart by iterating the embeddable's attributes. Each attribute must be a SingularPersistentAttribute — anonymous tuple model parts only support embeddables made of singular (basic/embeddable/entity) attributes. Any plural attribute (@OneToMany, @ManyToMany, @ElementCollection) inside the embeddable fails with IllegalArgumentException.","triggerScenarios":"Projecting a tuple/CTE result whose type is an embeddable that contains a collection attribute, then using that tuple as an embeddable-valued path (e.g., CTE attribute typed as the embeddable, or a select-new instantiation later navigated as embeddable).","commonSituations":"Value-object embeddables that grew a @ElementCollection over time; criteria/HQL queries with CTEs typed by domain embeddables; upgrading to Hibernate 6 where anonymous tuple model parts now validate attributes strictly.","solutions":["Remove the collection from the embeddable (embeddables with collections are a fragile mapping in general); model the collection on the owning entity instead","Project only the singular attributes into the tuple and map the result to a DTO class rather than the embeddable","Select the embeddable directly from its owning entity path rather than reconstructing it through a tuple/dynamic instantiation"],"exampleFix":"// before\n@Embeddable\nclass Address {\n    String city;\n    @ElementCollection\n    Set<String> phoneNumbers; // plural attribute breaks anonymous tuple part\n}\n\n// after\n@Embeddable\nclass Address {\n    String city;\n}\n// move phone numbers to the owning @Entity as @ElementCollection","handlingStrategy":"validation","validationCode":"// Guard at mapping time: embeddables used in tuple/CTE projections must be singular-only\nboolean hasPlural = embeddableType.getAttributes().stream().anyMatch(a -> !a.isCollection() == false); // i.e. a.isCollection()\nif (hasPlural) throw new IllegalArgumentException(\"Embeddable \" + embeddableType.getJavaType() + \" has collection attributes; unsupported in tuple projections\");","typeGuard":"static boolean isSingularOnly(ManagedType<?> type) { return type.getAttributes().stream().noneMatch(Attribute::isCollection); }","tryCatchPattern":"try { /* build tuple-typed query using the embeddable */ } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"without collections\")) { /* project singular attrs into a DTO instead */ } else throw e; }","preventionTips":["Keep embeddables used in CTE/tuple projections free of @ElementCollection/@OneToMany/@ManyToMany","Add an ArchUnit/mapping test asserting value embeddables contain only singular attributes","Prefer DTO classes for tuple projections over domain embeddables"],"tags":["hibernate","embeddable","collections","dynamic-instantiation","tuple","cte"],"backgroundTag":"embeddable-with-collections","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}