From 3600ffb7f2cdd3a4917221f3b0c4009ba0ebcadc Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Thu, 18 Apr 2013 12:47:18 -0500 Subject: [PATCH] HHH-7841 - Redesign Loader --- .../internal/ResultSetProcessorImpl.java | 3 + .../loader/plan/spi/CompositeFetch.java | 2 +- .../hibernate/loader/spi/LoadPlanAdvisor.java | 16 ++ .../graph/internal/advisor/AdviceHelper.java | 81 ++++++++ .../advisor/AdviceNodeDescriptor.java | 35 ++++ ...viceNodeDescriptorCollectionReference.java | 59 ++++++ ...dviceNodeDescriptorCompositeReference.java | 54 ++++++ .../AdviceNodeDescriptorEntityReference.java | 62 ++++++ .../graph/internal/advisor/AdviceStyle.java | 39 ++++ .../EntityGraphBasedLoadPlanAdvisor.java | 181 ++---------------- .../advisor/JpaGraphCollectionReference.java | 49 +++++ .../internal/advisor/JpaGraphReference.java | 53 +++++ .../JpaGraphReferenceSubGraphSupport.java | 101 ++++++++++ .../advisor/JpaGraphRootEntityReference.java | 95 +++++++++ .../JpaGraphSingularAttributeReference.java | 35 ++++ .../advisor/NoOpJpaGraphReference.java | 47 +++++ .../ReturnGraphVisitationStrategyImpl.java | 101 ++++++++++ .../metamodel/SingularAttributeImpl.java | 42 ++-- .../graphs/BasicGraphLoadPlanAdviceTests.java | 2 +- 19 files changed, 858 insertions(+), 199 deletions(-) create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceHelper.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptor.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorCollectionReference.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorCompositeReference.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorEntityReference.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceStyle.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphCollectionReference.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphReference.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphReferenceSubGraphSupport.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphRootEntityReference.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphSingularAttributeReference.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/NoOpJpaGraphReference.java create mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/ReturnGraphVisitationStrategyImpl.java diff --git a/hibernate-core/src/main/java/org/hibernate/loader/internal/ResultSetProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/loader/internal/ResultSetProcessorImpl.java index 0eea1dd1e5..f21430e194 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/internal/ResultSetProcessorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/internal/ResultSetProcessorImpl.java @@ -90,6 +90,9 @@ public class ResultSetProcessorImpl implements ResultSetProcessor { List afterLoadActionList) throws SQLException { final LoadPlan loadPlan = loadPlanAdvisor.advise( this.baseLoadPlan ); + if ( loadPlan == null ) { + throw new IllegalStateException( "LoadPlanAdvisor returned null" ); + } handlePotentiallyEmptyCollectionRootReturns( loadPlan, queryParameters.getCollectionKeys(), resultSet, session ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetch.java b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetch.java index 15081e7162..db6f8e44be 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/plan/spi/CompositeFetch.java @@ -46,7 +46,7 @@ public class CompositeFetch extends AbstractSingularAttributeFetch { public CompositeFetch( SessionFactoryImplementor sessionFactory, String alias, - AbstractFetchOwner owner, + FetchOwner owner, String ownerProperty) { super( sessionFactory, alias, LockMode.NONE, owner, ownerProperty, FETCH_PLAN ); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadPlanAdvisor.java b/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadPlanAdvisor.java index cb252206d9..e7c0e2c60e 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadPlanAdvisor.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/spi/LoadPlanAdvisor.java @@ -26,8 +26,24 @@ package org.hibernate.loader.spi; import org.hibernate.loader.plan.spi.LoadPlan; /** + * An advisor that can be made available to the {@link ResultSetProcessor} and {@link ScrollableResultSetProcessor}. + * + * The processors consult with the advisor, if one is provided, as a means to influence the load plan, meaning that + * the advisor might add fetches. A caveat is that any added fetches cannot be join fetches (they cannot alter the + * SQL); if a fetch is added as {@link org.hibernate.engine.FetchTiming#IMMEDIATE}, it must be a "subsequent form": + * {@link org.hibernate.engine.FetchStyle#SELECT}, {@link org.hibernate.engine.FetchStyle#SUBSELECT}, + * {@link org.hibernate.engine.FetchStyle#BATCH}. + * * @author Steve Ebersole */ public interface LoadPlanAdvisor { + /** + * Advise on the given LoadPlan, returning a new LoadPlan if any additions are needed. It is the responsibility + * of the advisor to return the original load plan if no additions were needed + * + * @param loadPlan The load plan to advise on. + * + * @return The original or advised load plan. + */ public LoadPlan advise(LoadPlan loadPlan); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceHelper.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceHelper.java new file mode 100644 index 0000000000..f5e2d3a3a9 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceHelper.java @@ -0,0 +1,81 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import org.hibernate.LockMode; +import org.hibernate.engine.FetchStrategy; +import org.hibernate.engine.FetchStyle; +import org.hibernate.engine.FetchTiming; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.graph.spi.AttributeNodeImplementor; +import org.hibernate.loader.plan.spi.CollectionFetch; +import org.hibernate.loader.plan.spi.CompositeFetch; +import org.hibernate.loader.plan.spi.EntityFetch; +import org.hibernate.loader.plan.spi.Fetch; +import org.hibernate.loader.plan.spi.FetchOwner; + +/** + * @author Steve Ebersole + */ +public class AdviceHelper { + private AdviceHelper() { + } + + static Fetch buildFetch(FetchOwner fetchOwner, AttributeNodeImplementor attributeNode) { + if ( attributeNode.getAttribute().isAssociation() ) { + if ( attributeNode.getAttribute().isCollection() ) { + return new CollectionFetch( + (SessionFactoryImplementor) attributeNode.entityManagerFactory().getSessionFactory(), + "abc-xyz", // alias + LockMode.NONE, + fetchOwner, + new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.SELECT ), + attributeNode.getAttributeName(), + null, // sql table alias + null // entityaliases + ); + } + else { + return new EntityFetch( + (SessionFactoryImplementor) attributeNode.entityManagerFactory().getSessionFactory(), + "abc-xyz", // alias + LockMode.NONE, + fetchOwner, + attributeNode.getAttributeName(), + new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.SELECT ), + null, // sql table alias + null // entityaliases + ); + } + } + else { + return new CompositeFetch( + (SessionFactoryImplementor) attributeNode.entityManagerFactory().getSessionFactory(), + "abc-xyz", // alias + fetchOwner, + attributeNode.getAttributeName() + ); + } + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptor.java new file mode 100644 index 0000000000..b3fca7ea2f --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptor.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +/** + * Links together the LoadPlan graph and JPA graph notions of the same node. + * + * @author Steve Ebersole + */ +interface AdviceNodeDescriptor { + public JpaGraphReference attributeProcessed(String attributeName); + + public void applyMissingFetches(); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorCollectionReference.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorCollectionReference.java new file mode 100644 index 0000000000..6939f641fd --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorCollectionReference.java @@ -0,0 +1,59 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import org.hibernate.loader.plan.spi.CollectionFetch; + +/** + * @author Steve Ebersole + */ +public class AdviceNodeDescriptorCollectionReference implements AdviceNodeDescriptor { + private final CollectionFetch collectionFetch; + private final JpaGraphReference jpaGraphReference; + + public AdviceNodeDescriptorCollectionReference( + CollectionFetch collectionFetch, + JpaGraphReference jpaGraphReference) { + //To change body of created methods use File | Settings | File Templates. + this.collectionFetch = collectionFetch; + this.jpaGraphReference = jpaGraphReference; + } + + @Override + public JpaGraphReference attributeProcessed(String attributeName) { + return jpaGraphReference != null + ? jpaGraphReference.attributeProcessed( attributeName ) + : null; + } + + @Override + public void applyMissingFetches() { + if ( jpaGraphReference == null ) { + return; + } + jpaGraphReference.applyMissingFetches( collectionFetch.getElementGraph() ); + ( (JpaGraphCollectionReference) jpaGraphReference ).applyMissingKeyFetches( collectionFetch.getIndexGraph() ); + + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorCompositeReference.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorCompositeReference.java new file mode 100644 index 0000000000..76173e3ca2 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorCompositeReference.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import org.hibernate.loader.plan.spi.CompositeFetch; +import org.hibernate.loader.plan.spi.FetchOwner; + +/** + * @author Steve Ebersole + */ +public class AdviceNodeDescriptorCompositeReference implements AdviceNodeDescriptor { + private final FetchOwner fetchOwner; + private final JpaGraphReference jpaGraphReference; + + AdviceNodeDescriptorCompositeReference(CompositeFetch fetchOwner, JpaGraphReference jpaGraphReference) { + this.fetchOwner = fetchOwner; + this.jpaGraphReference = jpaGraphReference; + } + + @Override + public JpaGraphReference attributeProcessed(String attributeName) { + return jpaGraphReference != null + ? jpaGraphReference.attributeProcessed( attributeName ) + : null; + } + + @Override + public void applyMissingFetches() { + if ( jpaGraphReference != null ) { + jpaGraphReference.applyMissingFetches( fetchOwner ); + } + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorEntityReference.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorEntityReference.java new file mode 100644 index 0000000000..79022edc96 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceNodeDescriptorEntityReference.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import org.hibernate.loader.plan.spi.EntityFetch; +import org.hibernate.loader.plan.spi.EntityReturn; +import org.hibernate.loader.plan.spi.FetchOwner; + +/** + * An AdviceNodeDescriptor that represents an entity reference + * + * @author Steve Ebersole + */ +class AdviceNodeDescriptorEntityReference implements AdviceNodeDescriptor { + private final FetchOwner fetchOwner; + private final JpaGraphReference jpaGraphReference; + + AdviceNodeDescriptorEntityReference(EntityReturn fetchOwner, JpaGraphReference jpaGraphReference) { + this.fetchOwner = fetchOwner; + this.jpaGraphReference = jpaGraphReference; + } + + AdviceNodeDescriptorEntityReference(EntityFetch fetchOwner, JpaGraphReference jpaGraphReference) { + this.fetchOwner = fetchOwner; + this.jpaGraphReference = jpaGraphReference; + } + + @Override + public JpaGraphReference attributeProcessed(String attributeName) { + return jpaGraphReference != null + ? jpaGraphReference.attributeProcessed( attributeName ) + : null; + } + + @Override + public void applyMissingFetches() { + if ( jpaGraphReference != null ) { + jpaGraphReference.applyMissingFetches( fetchOwner ); + } + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceStyle.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceStyle.java new file mode 100644 index 0000000000..43cc0fef89 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/AdviceStyle.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +/** The style of advice. This is defined by the JPA spec. See tha values for details. + * + * @author Steve Ebersole + */ +public enum AdviceStyle { + /** + * Indicates a graph specified by the {@code javax.persistence.fetchgraph} setting. + */ + FETCH, + /** + * Indicates a graph specified by the {@code javax.persistence.loadgraph} setting. + */ + LOAD +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/EntityGraphBasedLoadPlanAdvisor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/EntityGraphBasedLoadPlanAdvisor.java index 4144cd9a3e..4b603eae35 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/EntityGraphBasedLoadPlanAdvisor.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/EntityGraphBasedLoadPlanAdvisor.java @@ -23,29 +23,20 @@ */ package org.hibernate.jpa.graph.internal.advisor; -import java.util.ArrayDeque; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.jboss.logging.Logger; import org.hibernate.jpa.graph.internal.EntityGraphImpl; -import org.hibernate.jpa.graph.spi.AttributeNodeImplementor; import org.hibernate.loader.plan.internal.LoadPlanImpl; -import org.hibernate.loader.plan.spi.CollectionFetch; -import org.hibernate.loader.plan.spi.CompositeFetch; import org.hibernate.loader.plan.spi.CopyContext; -import org.hibernate.loader.plan.spi.EntityFetch; import org.hibernate.loader.plan.spi.EntityReturn; -import org.hibernate.loader.plan.spi.FetchOwner; import org.hibernate.loader.plan.spi.LoadPlan; import org.hibernate.loader.plan.spi.Return; import org.hibernate.loader.plan.spi.visit.ReturnGraphVisitationStrategy; -import org.hibernate.loader.plan.spi.visit.ReturnGraphVisitationStrategyAdapter; import org.hibernate.loader.spi.LoadPlanAdvisor; /** + * A LoadPlanAdvisor implementation for applying JPA "entity graph" fetches + * * @author Steve Ebersole */ public class EntityGraphBasedLoadPlanAdvisor implements LoadPlanAdvisor { @@ -54,6 +45,13 @@ public class EntityGraphBasedLoadPlanAdvisor implements LoadPlanAdvisor { private final EntityGraphImpl root; private final AdviceStyle adviceStyle; + /** + * Constricts a LoadPlanAdvisor for applying any additional fetches needed as indicated by the + * given entity graph. + * + * @param root The entity graph indicating the fetches. + * @param adviceStyle The style of advise (this is defikned + */ public EntityGraphBasedLoadPlanAdvisor(EntityGraphImpl root, AdviceStyle adviceStyle) { if ( root == null ) { throw new IllegalArgumentException( "EntityGraph cannot be null" ); @@ -62,6 +60,7 @@ public class EntityGraphBasedLoadPlanAdvisor implements LoadPlanAdvisor { this.adviceStyle = adviceStyle; } + @Override public LoadPlan advise(LoadPlan loadPlan) { if ( root == null ) { log.debug( "Skipping load plan advising: no entity graph was specified" ); @@ -119,16 +118,11 @@ public class EntityGraphBasedLoadPlanAdvisor implements LoadPlanAdvisor { return rootEntityReturn; } - public static enum AdviceStyle { - FETCH, - LOAD - } - public class CopyContextImpl implements CopyContext { private final ReturnGraphVisitationStrategyImpl strategy; public CopyContextImpl(EntityReturn entityReturn) { - strategy = new ReturnGraphVisitationStrategyImpl( entityReturn ); + strategy = new ReturnGraphVisitationStrategyImpl( entityReturn, root ); } @Override @@ -137,157 +131,4 @@ public class EntityGraphBasedLoadPlanAdvisor implements LoadPlanAdvisor { } } - public class ReturnGraphVisitationStrategyImpl extends ReturnGraphVisitationStrategyAdapter { - private ArrayDeque nodeStack = new ArrayDeque(); - - public ReturnGraphVisitationStrategyImpl(EntityReturn entityReturn) { - nodeStack.addFirst( new EntityReferenceDescriptor( entityReturn, new RootEntityGraphNode( root ) ) ); - } - - @Override - public void finishingRootReturn(Return rootReturn) { - nodeStack.removeFirst(); - super.finishingRootReturn( rootReturn ); - } - - @Override - public void finishingFetches(FetchOwner fetchOwner) { - nodeStack.peekFirst().applyMissingFetches(); - super.finishingFetches( fetchOwner ); - } - - @Override - public void startingEntityFetch(EntityFetch entityFetch) { - super.startingEntityFetch( entityFetch ); - - final NodeDescriptor currentNode = nodeStack.peekFirst(); - final String attributeName = entityFetch.getOwnerPropertyName(); - final JpaGraphReference fetchedGraphReference = currentNode.attributeProcessed( attributeName ); - nodeStack.addFirst( new EntityReferenceDescriptor( entityFetch, fetchedGraphReference ) ); - } - - @Override - public void finishingEntityFetch(EntityFetch entityFetch) { - nodeStack.removeFirst(); - super.finishingEntityFetch( entityFetch ); - } - - @Override - public void startingCollectionFetch(CollectionFetch collectionFetch) { - super.startingCollectionFetch( collectionFetch ); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void finishingCollectionFetch(CollectionFetch collectionFetch) { - super.finishingCollectionFetch( collectionFetch ); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void startingCompositeFetch(CompositeFetch fetch) { - super.startingCompositeFetch( fetch ); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void finishingCompositeFetch(CompositeFetch fetch) { - super.finishingCompositeFetch( fetch ); //To change body of overridden methods use File | Settings | File Templates. - } - } - - private static interface NodeDescriptor { - public JpaGraphReference attributeProcessed(String attributeName); - - public void applyMissingFetches(); - } - - private static abstract class AbstractNodeDescriptor implements NodeDescriptor { - private final FetchOwner fetchOwner; - private final JpaGraphReference jpaGraphReference; - - protected AbstractNodeDescriptor(FetchOwner fetchOwner, JpaGraphReference jpaGraphReference) { - this.fetchOwner = fetchOwner; - this.jpaGraphReference = jpaGraphReference; - } - - @Override - public JpaGraphReference attributeProcessed(String attributeName) { - if ( jpaGraphReference != null ) { - return jpaGraphReference.attributeProcessed( attributeName ); - } - else { - return null; - } - } - - @Override - public void applyMissingFetches() { - if ( jpaGraphReference != null ) { - jpaGraphReference.applyMissingFetches( fetchOwner ); - } - } - } - - private static class EntityReferenceDescriptor extends AbstractNodeDescriptor { - private EntityReferenceDescriptor(EntityReturn entityReturn, JpaGraphReference correspondingJpaGraphNode) { - super( entityReturn, correspondingJpaGraphNode ); - } - - @SuppressWarnings("unchecked") - public EntityReferenceDescriptor(EntityFetch entityFetch, JpaGraphReference jpaGraphReference) { - super( entityFetch, jpaGraphReference ); - } - } - - private static interface JpaGraphReference { - public JpaGraphReference attributeProcessed(String attributeName); - public void applyMissingFetches(FetchOwner fetchOwner); - } - - private static class RootEntityGraphNode implements JpaGraphReference { - private final Map graphAttributeMap; - - private RootEntityGraphNode(EntityGraphImpl entityGraph) { - graphAttributeMap = new HashMap(); - - final List> explicitAttributeNodes = entityGraph.attributeImplementorNodes(); - if ( explicitAttributeNodes != null ) { - for ( AttributeNodeImplementor node : explicitAttributeNodes ) { - graphAttributeMap.put( node.getAttributeName(), node ); - } - } - } - - @Override - public JpaGraphReference attributeProcessed(String attributeName) { - final AttributeNodeImplementor attributeNode = graphAttributeMap.remove( attributeName ); - - if ( attributeNode == null ) { - return null; - } - - return new SubGraphNode( attributeNode ); - } - - - @Override - public void applyMissingFetches(FetchOwner fetchOwner) { - for ( AttributeNodeImplementor attributeNode : graphAttributeMap.values() ) { - System.out.println( "Found unprocessed attribute node : " + attributeNode.getAttributeName() ); - } - } - } - - private static class SubGraphNode implements JpaGraphReference { - protected SubGraphNode(AttributeNodeImplementor attributeNode) { - } - - @Override - public JpaGraphReference attributeProcessed(String attributeName) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public void applyMissingFetches(FetchOwner fetchOwner) { - //To change body of implemented methods use File | Settings | File Templates. - } - } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphCollectionReference.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphCollectionReference.java new file mode 100644 index 0000000000..f97ee4f2ea --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphCollectionReference.java @@ -0,0 +1,49 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import org.hibernate.jpa.graph.spi.AttributeNodeImplementor; +import org.hibernate.loader.plan.spi.FetchOwner; + +/** + * @author Steve Ebersole + */ +class JpaGraphCollectionReference extends JpaGraphReferenceSubGraphSupport { + private final AttributeNodeImplementor attributeNode; + + JpaGraphCollectionReference(AttributeNodeImplementor attributeNode) { + super( attributeNode ); + this.attributeNode = attributeNode; + } + + @Override + public void applyMissingFetches(FetchOwner fetchOwner) { + super.applyMissingFetches( fetchOwner ); + // todo : additionally we need to process key graph(s) + } + + void applyMissingKeyFetches(FetchOwner fetchOwner) { + // todo : additionally we need to process key graph(s) + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphReference.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphReference.java new file mode 100644 index 0000000000..4fa07ec80d --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphReference.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import org.hibernate.loader.plan.spi.FetchOwner; + +/** + * Describes a reference to a JPA graph. This encompasses both {@link javax.persistence.EntityGraph} + * and {@link javax.persistence.Subgraph}. Exposes the functionality needed for advising in a common way. + * + * @author Steve Ebersole + */ +interface JpaGraphReference { + /** + * Callback to let the JPA graph reference node know that the particular attribute (by name) was processed, which + * means it already was accounted for in the LoadPlan graph. For association attributes and composites, also + * returns a representation of the corresponding JPA graph node. + * + * @param attributeName The name of the attribute processed. + * + * @return The JPA graph reference corresponding to that attribute, if one. + */ + public JpaGraphReference attributeProcessed(String attributeName); + + /** + * For any attributes that are defined in the JPA graph, that were not processed (as would have been indicated + * by a previous call to {@link #attributeProcessed}), apply needed fetches to the fetch owner. + * + * @param fetchOwner The owner of any generated fetches. + */ + public void applyMissingFetches(FetchOwner fetchOwner); +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphReferenceSubGraphSupport.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphReferenceSubGraphSupport.java new file mode 100644 index 0000000000..8341fb06db --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphReferenceSubGraphSupport.java @@ -0,0 +1,101 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import javax.persistence.AttributeNode; +import javax.persistence.Subgraph; +import java.util.HashMap; +import java.util.Map; + +import org.jboss.logging.Logger; + +import org.hibernate.jpa.graph.spi.AttributeNodeImplementor; +import org.hibernate.loader.plan.spi.FetchOwner; + +/** + * @author Steve Ebersole + */ +abstract class JpaGraphReferenceSubGraphSupport implements JpaGraphReference { + private static final Logger log = Logger.getLogger( JpaGraphReferenceSubGraphSupport.class ); + + private final Map elementGraphAttributeMap; + + + protected JpaGraphReferenceSubGraphSupport(AttributeNodeImplementor attributeNode) { + this.elementGraphAttributeMap = new HashMap(); + + for ( Subgraph subgraph : attributeNode.getSubgraphs().values() ) { + for ( AttributeNode subGraphAttributeNode : subgraph.getAttributeNodes() ) { + final AttributeNodeImplementor nodeImplementor = (AttributeNodeImplementor) subGraphAttributeNode; + final AttributeNodeImplementor old = this.elementGraphAttributeMap.put( + nodeImplementor.getAttributeName(), + nodeImplementor + ); + + if ( old != null && old != nodeImplementor ) { + throw new IllegalStateException( + "Found multiple representations of the same attribute : " + nodeImplementor.getAttributeName() + ); + } + } + } + } + + @Override + public JpaGraphReference attributeProcessed(String attributeName) { + final AttributeNodeImplementor attributeNode = this.elementGraphAttributeMap.remove( attributeName ); + + if ( attributeNode == null ) { + return NoOpJpaGraphReference.INSTANCE; + } + + return attributeNode.getAttribute().isCollection() + ? new JpaGraphCollectionReference( attributeNode ) + : new JpaGraphSingularAttributeReference( attributeNode ); + } + + @Override + public void applyMissingFetches(FetchOwner fetchOwner) { + for ( AttributeNodeImplementor attributeNode : elementGraphAttributeMap.values() ) { + System.out.println( + String.format( + "Found unprocessed attribute node [%s], applying to fetch-owner [%s]", + attributeNode.getAttributeName(), + fetchOwner.getPropertyPath().getFullPath() + ) + ); + + log.tracef( + "Found unprocessed attribute node [%s], applying to fetch-owner [%s]", + attributeNode.getAttributeName(), + fetchOwner.getPropertyPath() + ); + + AdviceHelper.buildFetch( fetchOwner, attributeNode ); + + // todo : additionally we need to process any further graphs in the attribute node path + // since we are effectively at a leaf in the LoadPlan graph + } + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphRootEntityReference.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphRootEntityReference.java new file mode 100644 index 0000000000..46cd884053 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphRootEntityReference.java @@ -0,0 +1,95 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jboss.logging.Logger; + +import org.hibernate.jpa.graph.internal.EntityGraphImpl; +import org.hibernate.jpa.graph.spi.AttributeNodeImplementor; +import org.hibernate.loader.plan.spi.FetchOwner; + +/** + * Models the root {@link javax.persistence.EntityGraph} as a JpaGraphReference + * + * @author Steve Ebersole + */ +class JpaGraphRootEntityReference implements JpaGraphReference { + private static final Logger log = Logger.getLogger( JpaGraphRootEntityReference.class ); + + private final Map graphAttributeMap; + + JpaGraphRootEntityReference(EntityGraphImpl entityGraph) { + graphAttributeMap = new HashMap(); + + final List> explicitAttributeNodes = entityGraph.attributeImplementorNodes(); + if ( explicitAttributeNodes != null ) { + for ( AttributeNodeImplementor node : explicitAttributeNodes ) { + graphAttributeMap.put( node.getAttributeName(), node ); + } + } + } + + @Override + public JpaGraphReference attributeProcessed(String attributeName) { + final AttributeNodeImplementor attributeNode = graphAttributeMap.remove( attributeName ); + + if ( attributeNode == null ) { + return NoOpJpaGraphReference.INSTANCE; + } + + return attributeNode.getAttribute().isCollection() + ? new JpaGraphCollectionReference( attributeNode ) + : new JpaGraphSingularAttributeReference( attributeNode ); + } + + + @Override + public void applyMissingFetches(FetchOwner fetchOwner) { + for ( AttributeNodeImplementor attributeNode : graphAttributeMap.values() ) { + System.out.println( + String.format( + "Found unprocessed attribute node [%s], applying to fetch-owner [%s]", + attributeNode.getAttributeName(), + fetchOwner.getPropertyPath().getFullPath() + ) + ); + + log.tracef( + "Found unprocessed attribute node [%s], applying to fetch-owner [%s]", + attributeNode.getAttributeName(), + fetchOwner.getPropertyPath() + ); + + AdviceHelper.buildFetch( fetchOwner, attributeNode ); + + // todo : additionally we need to process any further graphs in the attribute node path + // since we are effectively at a leaf in the LoadPlan graph + } + } + +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphSingularAttributeReference.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphSingularAttributeReference.java new file mode 100644 index 0000000000..d9cd03099f --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/JpaGraphSingularAttributeReference.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import org.hibernate.jpa.graph.spi.AttributeNodeImplementor; + +/** +* @author Steve Ebersole +*/ +class JpaGraphSingularAttributeReference extends JpaGraphReferenceSubGraphSupport { + JpaGraphSingularAttributeReference(AttributeNodeImplementor attributeNode) { + super( attributeNode ); + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/NoOpJpaGraphReference.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/NoOpJpaGraphReference.java new file mode 100644 index 0000000000..9763ef6c7b --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/NoOpJpaGraphReference.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import org.hibernate.loader.plan.spi.FetchOwner; + +/** + * A no-op implementation of JpaGraphReference. Used when the LoadPlan graph already defines + * nodes beyond the scope of the JPA graph. + * + * @author Steve Ebersole + */ +class NoOpJpaGraphReference implements JpaGraphReference { + public static final NoOpJpaGraphReference INSTANCE = new NoOpJpaGraphReference(); + + @Override + public JpaGraphReference attributeProcessed(String attributeName) { + // its no-op, nothing to do + return INSTANCE; + } + + @Override + public void applyMissingFetches(FetchOwner fetchOwner) { + // its no-op, nothing to do + } +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/ReturnGraphVisitationStrategyImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/ReturnGraphVisitationStrategyImpl.java new file mode 100644 index 0000000000..fcecaf5697 --- /dev/null +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/graph/internal/advisor/ReturnGraphVisitationStrategyImpl.java @@ -0,0 +1,101 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.graph.internal.advisor; + +import java.util.ArrayDeque; + +import org.hibernate.jpa.graph.internal.EntityGraphImpl; +import org.hibernate.loader.plan.spi.CollectionFetch; +import org.hibernate.loader.plan.spi.CompositeFetch; +import org.hibernate.loader.plan.spi.EntityFetch; +import org.hibernate.loader.plan.spi.EntityReturn; +import org.hibernate.loader.plan.spi.FetchOwner; +import org.hibernate.loader.plan.spi.Return; +import org.hibernate.loader.plan.spi.visit.ReturnGraphVisitationStrategyAdapter; + +/** + * The visitor strategy for visiting the return graph of the load plan being advised. + * + * @author Steve Ebersole + */ +public class ReturnGraphVisitationStrategyImpl extends ReturnGraphVisitationStrategyAdapter { + private ArrayDeque nodeStack = new ArrayDeque(); + + public ReturnGraphVisitationStrategyImpl(EntityReturn entityReturn, EntityGraphImpl jpaRoot) { + nodeStack.addFirst( new AdviceNodeDescriptorEntityReference( entityReturn, new JpaGraphRootEntityReference( jpaRoot ) ) ); + } + + @Override + public void finishingRootReturn(Return rootReturn) { + nodeStack.removeFirst(); + } + + @Override + public void finishingFetches(FetchOwner fetchOwner) { + nodeStack.peekFirst().applyMissingFetches(); + } + + @Override + public void startingEntityFetch(EntityFetch entityFetch) { + final AdviceNodeDescriptor currentNode = nodeStack.peekFirst(); + final String attributeName = entityFetch.getOwnerPropertyName(); + final JpaGraphReference fetchedGraphReference = currentNode.attributeProcessed( attributeName ); + + nodeStack.addFirst( new AdviceNodeDescriptorEntityReference( entityFetch, fetchedGraphReference ) ); + } + + @Override + public void finishingEntityFetch(EntityFetch entityFetch) { + nodeStack.removeFirst(); + } + + @Override + public void startingCollectionFetch(CollectionFetch collectionFetch) { + final AdviceNodeDescriptor currentNode = nodeStack.peekFirst(); + final String attributeName = collectionFetch.getOwnerPropertyName(); + final JpaGraphReference fetchedGraphReference = currentNode.attributeProcessed( attributeName ); + + nodeStack.addFirst( new AdviceNodeDescriptorCollectionReference( collectionFetch, fetchedGraphReference ) ); + } + + @Override + public void finishingCollectionFetch(CollectionFetch collectionFetch) { + nodeStack.removeFirst(); + } + + @Override + public void startingCompositeFetch(CompositeFetch fetch) { + final AdviceNodeDescriptor currentNode = nodeStack.peekFirst(); + final String attributeName = fetch.getOwnerPropertyName(); + final JpaGraphReference fetchedGraphReference = currentNode.attributeProcessed( attributeName ); + + nodeStack.addFirst( new AdviceNodeDescriptorCompositeReference( fetch, fetchedGraphReference ) ); + } + + @Override + public void finishingCompositeFetch(CompositeFetch fetch) { + nodeStack.removeFirst(); + } + +} diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/SingularAttributeImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/SingularAttributeImpl.java index e0b42b64da..bb28edc5e9 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/SingularAttributeImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/metamodel/SingularAttributeImpl.java @@ -1,8 +1,10 @@ /* - * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2009, 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Middleware LLC. + * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU @@ -20,6 +22,7 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.jpa.internal.metamodel; + import java.io.Serializable; import java.lang.reflect.Member; import javax.persistence.metamodel.SingularAttribute; @@ -86,58 +89,43 @@ public class SingularAttributeImpl } } - /** - * {@inheritDoc} - */ + @Override public boolean isId() { return isIdentifier; } - /** - * {@inheritDoc} - */ + @Override public boolean isVersion() { return isVersion; } - /** - * {@inheritDoc} - */ + @Override public boolean isOptional() { return isOptional; } - /** - * {@inheritDoc} - */ + @Override public Type getType() { return attributeType; } - /** - * {@inheritDoc} - */ + @Override public boolean isAssociation() { - return false; + return getPersistentAttributeType() == PersistentAttributeType.MANY_TO_ONE + || getPersistentAttributeType() == PersistentAttributeType.ONE_TO_ONE; } - /** - * {@inheritDoc} - */ + @Override public boolean isCollection() { return false; } - /** - * {@inheritDoc} - */ + @Override public BindableType getBindableType() { return BindableType.SINGULAR_ATTRIBUTE; } - /** - * {@inheritDoc} - */ + @Override public Class getBindableJavaType() { return attributeType.getJavaType(); } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/BasicGraphLoadPlanAdviceTests.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/BasicGraphLoadPlanAdviceTests.java index 2e749c961c..949a827118 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/BasicGraphLoadPlanAdviceTests.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/graphs/BasicGraphLoadPlanAdviceTests.java @@ -46,7 +46,7 @@ import org.hibernate.persister.entity.Loadable; import org.junit.Test; -import static org.hibernate.jpa.graph.internal.advisor.EntityGraphBasedLoadPlanAdvisor.AdviceStyle; +import org.hibernate.jpa.graph.internal.advisor.AdviceStyle; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull;