From 02c86507ba94029603f925f54e4069fcb2b5ab89 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Thu, 16 Jun 2016 14:29:32 +0100 Subject: [PATCH] HHH-8488 - Fix Join, CollectionJoin, SetJoin, ListJoin, MapJoin CriteriaBuilder#treat SetJoin behaviour (cherry picked from commit 20f68d43a45b0aad724ac1023f6f846c5d88438b) --- .../jpa/criteria/CriteriaBuilderImpl.java | 24 ++++++++++---- .../jpa/criteria/FromImplementor.java | 14 +++++--- .../jpa/criteria/QueryStructure.java | 12 ++++--- .../path/CollectionAttributeJoin.java | 33 +++++++++++++++++-- .../jpa/criteria/path/ListAttributeJoin.java | 33 +++++++++++++++++-- .../jpa/criteria/path/MapAttributeJoin.java | 33 +++++++++++++++++-- .../jpa/criteria/path/SetAttributeJoin.java | 33 +++++++++++++++++-- .../criteria/path/SingularAttributeJoin.java | 32 ++++++++++++++++-- 8 files changed, 187 insertions(+), 27 deletions(-) diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/CriteriaBuilderImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/CriteriaBuilderImpl.java index 3a1c1f6ae8..9fc6db6f80 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/CriteriaBuilderImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/CriteriaBuilderImpl.java @@ -15,6 +15,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.BiFunction; import javax.persistence.Tuple; import javax.persistence.criteria.CollectionJoin; import javax.persistence.criteria.CompoundSelection; @@ -1101,31 +1102,31 @@ public class CriteriaBuilderImpl implements CriteriaBuilder, Serializable { @Override @SuppressWarnings("unchecked") public Join treat(Join join, Class type) { - return ( (JoinImplementor) join ).treatAs( type ); + return treat( join, type, (j, t) -> ((JoinImplementor) j).treatAs( t ) ); } @Override @SuppressWarnings("unchecked") public CollectionJoin treat(CollectionJoin join, Class type) { - return ( (CollectionJoinImplementor) join ).treatAs( type ); + return treat( join, type, (j, t) -> ((CollectionJoinImplementor) j).treatAs( t ) ); } @Override @SuppressWarnings("unchecked") public SetJoin treat(SetJoin join, Class type) { - return ( (SetJoinImplementor) join ).treatAs( type ); + return treat( join, type, (j, t) -> ((SetJoinImplementor) j).treatAs( t ) ); } @Override @SuppressWarnings("unchecked") public ListJoin treat(ListJoin join, Class type) { - return ( (ListJoinImplementor) join ).treatAs( type ); + return treat( join, type, (j, t) -> ((ListJoinImplementor) join).treatAs( type ) ); } @Override @SuppressWarnings("unchecked") public MapJoin treat(MapJoin join, Class type) { - return ( (MapJoinImplementor) join ).treatAs( type ); + return treat( join, type, (j, t) -> ((MapJoinImplementor) join).treatAs( type ) ); } @Override @@ -1137,10 +1138,9 @@ public class CriteriaBuilderImpl implements CriteriaBuilder, Serializable { @Override @SuppressWarnings("unchecked") public Root treat(Root root, Class type) { - return ( (RootImpl) root ).treatAs( type ); + return ((RootImpl) root).treatAs( type ); } - // subqueries ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override @@ -1346,4 +1346,14 @@ public class CriteriaBuilderImpl implements CriteriaBuilder, Serializable { public > Predicate isNotMember(Expression eExpression, Expression cExpression) { return isMember(eExpression, cExpression).not(); } + + private K treat( + Join join, + Class type, + BiFunction, Class, K> f) { + final Set> joins = join.getParent().getJoins(); + final K treatAs = f.apply( join, type ); + joins.add(treatAs); + return treatAs; + } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/FromImplementor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/FromImplementor.java index add801a98f..8bf39c26bc 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/FromImplementor.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/FromImplementor.java @@ -15,11 +15,15 @@ import org.hibernate.jpa.criteria.compile.RenderingContext; * @author Steve Ebersole */ public interface FromImplementor extends PathImplementor, From { - public void prepareAlias(RenderingContext renderingContext); - public String renderTableExpression(RenderingContext renderingContext); + void prepareAlias(RenderingContext renderingContext); + String renderTableExpression(RenderingContext renderingContext); - public FromImplementor correlateTo(CriteriaSubqueryImpl subquery); - public void prepareCorrelationDelegate(FromImplementor parent); - public FromImplementor getCorrelationParent(); + FromImplementor correlateTo(CriteriaSubqueryImpl subquery); + void prepareCorrelationDelegate(FromImplementor parent); + FromImplementor getCorrelationParent(); + + default boolean shouldBeRendered(){ + return true; + } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/QueryStructure.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/QueryStructure.java index cfca1cc9d0..4931f93feb 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/QueryStructure.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/QueryStructure.java @@ -336,11 +336,13 @@ public class QueryStructure implements Serializable { } for ( Join join : joins ) { - ( (FromImplementor) join ).prepareAlias( renderingContext ); - jpaqlQuery.append( renderJoinType( join.getJoinType() ) ) - .append( ( (FromImplementor) join ).renderTableExpression( renderingContext ) ); - renderJoins( jpaqlQuery, renderingContext, join.getJoins() ); - renderFetches( jpaqlQuery, renderingContext, join.getFetches() ); + if ( ((FromImplementor) join).shouldBeRendered() ) { + ((FromImplementor) join).prepareAlias( renderingContext ); + jpaqlQuery.append( renderJoinType( join.getJoinType() ) ) + .append( ((FromImplementor) join).renderTableExpression( renderingContext ) ); + renderJoins( jpaqlQuery, renderingContext, join.getJoins() ); + renderFetches( jpaqlQuery, renderingContext, join.getFetches() ); + } } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/CollectionAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/CollectionAttributeJoin.java index 7d84e40b4d..eb8e3a87d6 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/CollectionAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/CollectionAttributeJoin.java @@ -12,6 +12,7 @@ import javax.persistence.criteria.Expression; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Predicate; import javax.persistence.metamodel.CollectionAttribute; +import javax.persistence.metamodel.ManagedType; import org.hibernate.jpa.criteria.CollectionJoinImplementor; import org.hibernate.jpa.criteria.CriteriaBuilderImpl; @@ -97,12 +98,35 @@ public class CollectionAttributeJoin @Override public String getAlias() { - return original.getAlias(); + return isCorrelated() ? getCorrelationParent().getAlias() : super.getAlias(); } @Override public void prepareAlias(RenderingContext renderingContext) { - // do nothing... + if ( getAlias() == null ) { + if ( isCorrelated() ) { + setAlias( getCorrelationParent().getAlias() ); + } + else { + setAlias( renderingContext.generateAlias() ); + } + } + } + + @Override + protected void setAlias(String alias) { + super.setAlias( alias ); + original.setAlias( alias ); + } + + @Override + public boolean shouldBeRendered() { + if ( getJoins().size() > 0 ) { + return true; + } + else { + return false; + } } @Override @@ -110,6 +134,11 @@ public class CollectionAttributeJoin return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } + @Override + protected ManagedType locateManagedType() { + return criteriaBuilder().getEntityManagerFactory().getMetamodel().managedType( treatAsType ); + } + @Override public String getPathIdentifier() { return "treat(" + getAlias() + " as " + treatAsType.getName() + ")"; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/ListAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/ListAttributeJoin.java index 0dff32b867..6b57d278ed 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/ListAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/ListAttributeJoin.java @@ -12,6 +12,7 @@ import javax.persistence.criteria.Expression; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Predicate; import javax.persistence.metamodel.ListAttribute; +import javax.persistence.metamodel.ManagedType; import org.hibernate.jpa.criteria.CriteriaBuilderImpl; import org.hibernate.jpa.criteria.CriteriaSubqueryImpl; @@ -105,12 +106,35 @@ public class ListAttributeJoin @Override public String getAlias() { - return original.getAlias(); + return isCorrelated() ? getCorrelationParent().getAlias() : super.getAlias(); } @Override public void prepareAlias(RenderingContext renderingContext) { - // do nothing... + if ( getAlias() == null ) { + if ( isCorrelated() ) { + setAlias( getCorrelationParent().getAlias() ); + } + else { + setAlias( renderingContext.generateAlias() ); + } + } + } + + @Override + protected void setAlias(String alias) { + super.setAlias( alias ); + original.setAlias( alias ); + } + + @Override + public boolean shouldBeRendered() { + if ( getJoins().size() > 0 ) { + return true; + } + else { + return false; + } } @Override @@ -118,6 +142,11 @@ public class ListAttributeJoin return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } + @Override + protected ManagedType locateManagedType() { + return criteriaBuilder().getEntityManagerFactory().getMetamodel().managedType( treatAsType ); + } + @Override public String getPathIdentifier() { return "treat(" + getAlias() + " as " + treatAsType.getName() + ")"; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/MapAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/MapAttributeJoin.java index 90f096d5a7..2f7ad0fa42 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/MapAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/MapAttributeJoin.java @@ -12,6 +12,7 @@ import javax.persistence.criteria.Expression; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; +import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.MapAttribute; import org.hibernate.jpa.criteria.CriteriaBuilderImpl; @@ -126,12 +127,35 @@ public class MapAttributeJoin @Override public String getAlias() { - return original.getAlias(); + return isCorrelated() ? getCorrelationParent().getAlias() : super.getAlias(); } @Override public void prepareAlias(RenderingContext renderingContext) { - // do nothing... + if ( getAlias() == null ) { + if ( isCorrelated() ) { + setAlias( getCorrelationParent().getAlias() ); + } + else { + setAlias( renderingContext.generateAlias() ); + } + } + } + + @Override + protected void setAlias(String alias) { + super.setAlias( alias ); + original.setAlias( alias ); + } + + @Override + public boolean shouldBeRendered() { + if ( getJoins().size() > 0 ) { + return true; + } + else { + return false; + } } @Override @@ -139,6 +163,11 @@ public class MapAttributeJoin return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } + @Override + protected ManagedType locateManagedType() { + return criteriaBuilder().getEntityManagerFactory().getMetamodel().managedType( treatAsType ); + } + @Override public String getPathIdentifier() { return "treat(" + getAlias() + " as " + treatAsType.getName() + ")"; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SetAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SetAttributeJoin.java index 8938ac014b..62a22bba1f 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SetAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SetAttributeJoin.java @@ -11,6 +11,7 @@ import java.util.Set; import javax.persistence.criteria.Expression; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Predicate; +import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.SetAttribute; import org.hibernate.jpa.criteria.CriteriaBuilderImpl; @@ -102,12 +103,35 @@ public class SetAttributeJoin @Override public String getAlias() { - return original.getAlias(); + return isCorrelated() ? getCorrelationParent().getAlias() : super.getAlias(); } @Override public void prepareAlias(RenderingContext renderingContext) { - // do nothing... + if ( getAlias() == null ) { + if ( isCorrelated() ) { + setAlias( getCorrelationParent().getAlias() ); + } + else { + setAlias( renderingContext.generateAlias() ); + } + } + } + + @Override + protected void setAlias(String alias) { + super.setAlias( alias ); + original.setAlias( alias ); + } + + @Override + public boolean shouldBeRendered() { + if ( getJoins().size() > 0 ) { + return true; + } + else { + return false; + } } @Override @@ -115,6 +139,11 @@ public class SetAttributeJoin return "treat(" + original.render( renderingContext ) + " as " + treatAsType.getName() + ")"; } + @Override + protected ManagedType locateManagedType() { + return criteriaBuilder().getEntityManagerFactory().getMetamodel().managedType( treatAsType ); + } + @Override public String getPathIdentifier() { return "treat(" + getAlias() + " as " + treatAsType.getName() + ")"; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SingularAttributeJoin.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SingularAttributeJoin.java index 06f6064b4f..9b3212b22e 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SingularAttributeJoin.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/SingularAttributeJoin.java @@ -133,12 +133,40 @@ public class SingularAttributeJoin extends AbstractJoinImpl { @Override public String getAlias() { - return original.getAlias(); + return isCorrelated() ? getCorrelationParent().getAlias() : super.getAlias(); } @Override public void prepareAlias(RenderingContext renderingContext) { - // do nothing... + if ( getAlias() == null ) { + if ( isCorrelated() ) { + setAlias( getCorrelationParent().getAlias() ); + } + else { + setAlias( renderingContext.generateAlias() ); + } + } + } + + @Override + protected void setAlias(String alias) { + super.setAlias( alias ); + original.setAlias( alias ); + } + + @Override + protected ManagedType locateManagedType() { + return criteriaBuilder().getEntityManagerFactory().getMetamodel().managedType( treatAsType ); + } + + @Override + public boolean shouldBeRendered() { + if ( getJoins().size() > 0 ) { + return true; + } + else { + return false; + } } @Override