Skip to content

Commit

Permalink
HHH-17528 Throw error for embedded result with collections
Browse files Browse the repository at this point in the history
  • Loading branch information
mbladel authored and beikov committed Dec 15, 2023
1 parent a59119e commit b44ff03
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -610,3 +610,11 @@ create table JsonHolder as (
====

Again, the name and the nullability of the `aggregate` column can be refined through applying a `@Column` on the persistent attribute.

[[embeddable-mapping-aggregate]]
==== Embeddable mappings containing collections

Mapping <<chapters/domain/collections.adoc#collections,collections>> inside an `@Embeddable` value is supported in most cases. There are a couple exceptions:

* If the values of an <<chapters/domain/collections.adoc#collections-elemental,@ElementCollection>> is of embeddable type, that embeddable cannot contain nested collections;
* Explicitly selecting an embeddable that contains collections in a query is currently not supported (we wouldn't be able to correctly initialize the collection since its owning entity instance would be missing from the Persistence Context).
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
*/
package org.hibernate.sql.results.graph.embeddable.internal;

import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.query.SemanticException;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.FromClauseAccess;
Expand Down Expand Up @@ -41,8 +43,14 @@ public EmbeddableResultImpl(
String resultVariable,
DomainResultCreationState creationState) {
super( navigablePath );

this.fetchContainer = modelPart.getEmbeddableTypeDescriptor();
this.resultVariable = resultVariable;

// We currently don't support explicitly selecting embeddables that contain collections
// as we wouldn't be able to correctly initialize their owning entity instances
checkContainsCollections( modelPart, navigablePath );

/*
An `{embeddable_result}` sub-path is created for the corresponding initializer to differentiate it from a fetch-initializer if this embedded is also fetched.
The Jakarta Persistence spec says that any embedded value selected in the result should not be part of the state of any managed entity.
Expand Down Expand Up @@ -88,6 +96,25 @@ private static boolean determineIfContainedAnyScalars(ImmutableFetchList fetches
return false;
}

private static void checkContainsCollections(
EmbeddableValuedModelPart embeddableModelPart,
NavigablePath navigablePath) {
embeddableModelPart.forEachSubPart( (index, modelPart) -> {
final AttributeMapping attribute = modelPart.asAttributeMapping();
if ( attribute != null ) {
if ( attribute.isPluralAttributeMapping() ) {
throw new SemanticException( String.format(
"Explicit selection of an embeddable containing collections is not supported: %s",
navigablePath
) );
}
else if ( attribute.isEmbeddedAttributeMapping() ) {
checkContainsCollections( attribute.asEmbeddedAttributeMapping(), navigablePath );
}
}
} );
}

@Override
public String getResultVariable() {
return resultVariable;
Expand Down

0 comments on commit b44ff03

Please sign in to comment.