diff --git a/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java b/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java index a2278e11d..eb5020ce2 100644 --- a/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java +++ b/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java @@ -15,17 +15,8 @@ */ package org.springframework.data.jpa.provider; -import static org.springframework.data.jpa.provider.JpaClassUtils.isEntityManagerOfType; -import static org.springframework.data.jpa.provider.JpaClassUtils.isMetamodelOfType; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.ECLIPSELINK_ENTITY_MANAGER_INTERFACE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.ECLIPSELINK_JPA_METAMODEL_TYPE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.GENERIC_JPA_ENTITY_MANAGER_INTERFACE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.HIBERNATE43_ENTITY_MANAGER_INTERFACE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.HIBERNATE43_JPA_METAMODEL_TYPE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.HIBERNATE_ENTITY_MANAGER_INTERFACE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.HIBERNATE_JPA_METAMODEL_TYPE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.OPENJPA_ENTITY_MANAGER_INTERFACE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.OPENJPA_JPA_METAMODEL_TYPE; +import static org.springframework.data.jpa.provider.JpaClassUtils.*; +import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.*; import java.util.Arrays; import java.util.Collection; @@ -33,10 +24,8 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; -import javax.persistence.EntityGraph; import javax.persistence.EntityManager; import javax.persistence.Query; -import javax.persistence.Subgraph; import javax.persistence.metamodel.Metamodel; import org.apache.openjpa.enhance.PersistenceCapable; @@ -53,12 +42,10 @@ import org.hibernate.ScrollableResults; import org.hibernate.ejb.HibernateQuery; import org.hibernate.proxy.HibernateProxy; import org.springframework.beans.DirectFieldAccessor; -import org.springframework.data.jpa.repository.query.JpaEntityGraph; import org.springframework.data.util.CloseableIterator; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; /** * Enumeration representing persistence providers to be used. @@ -367,69 +354,6 @@ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor { + name()); } - /** - * Creates a dynamic {@link EntityGraph} from the given {@link JpaEntityGraph} information. - * - * @param em - * @param jpaEntityGraph - * @param entityType - * @return - * - * @since 1.9 - */ - public EntityGraph createDynamicEntityGraph(EntityManager em, JpaEntityGraph jpaEntityGraph, Class entityType) { - - Assert.isTrue(jpaEntityGraph.isDynamicEntityGraph(), "The given " + jpaEntityGraph + " is not dynamic!"); - - EntityGraph entityGraph = em.createEntityGraph(entityType); - - configureFetchGraphFrom(jpaEntityGraph, entityGraph); - - return entityGraph; - } - - - /** - * Configures the given {@link EntityGraph} with the fetch graph information stored in {@link JpaEntityGraph}. - * - * @param jpaEntityGraph - * @param entityGraph - */ - /* visible for testing */ - void configureFetchGraphFrom(JpaEntityGraph jpaEntityGraph, EntityGraph entityGraph) { - - String[] attributePaths = jpaEntityGraph.getAttributePaths().clone(); - - // sort to ensure that the intermediate entity subgraphs are created accordingly. - Arrays.sort(attributePaths); - - // we build the entity graph based on the paths with highest depth first - for (int i = attributePaths.length - 1; i >= 0; i--) { - - String path = attributePaths[i]; - - //fast path just single attribute - if (!path.contains(".")) { - entityGraph.addAttributeNodes(path); - continue; - } - - //we need to build nested sub fetch graphs - String[] pathComponents = StringUtils.delimitedListToStringArray(path, "."); - - Subgraph parent = null; - for (int c = 0; c < pathComponents.length - 1; c++) { - - if (c == 0) { - parent = entityGraph.addSubgraph(pathComponents[c]); - } else { - parent = parent.addSubgraph(pathComponents[c]); - } - } - parent.addAttributeNodes(pathComponents[pathComponents.length - 1]); - } - } - /** * {@link CloseableIterator} for Hibernate. * diff --git a/src/main/java/org/springframework/data/jpa/repository/query/Jpa21Utils.java b/src/main/java/org/springframework/data/jpa/repository/query/Jpa21Utils.java index 87aa84fbf..f253d7818 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/Jpa21Utils.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/Jpa21Utils.java @@ -16,17 +16,20 @@ package org.springframework.data.jpa.repository.query; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; import javax.persistence.EntityGraph; import javax.persistence.EntityManager; import javax.persistence.Query; +import javax.persistence.Subgraph; -import org.springframework.data.jpa.provider.PersistenceProvider; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; /** * Utils for bridging various JPA 2.1 features. @@ -57,11 +60,10 @@ public class Jpa21Utils { /** * Returns a {@link Map} with hints for a JPA 2.1 fetch-graph or load-graph if running under JPA 2.1. * - * @param em must not be {@literal null} - * @param query must not be {@literal null} - * @param entityGraph can be {@literal null} - * @param entityType must not be {@literal null} - * @return a {@code Map} with the hints or an empty {@code Map} if no hints were found + * @param em must not be {@literal null}. + * @param entityGraph can be {@literal null}. + * @param entityType must not be {@literal null}. + * @return a {@code Map} with the hints or an empty {@code Map} if no hints were found. * @since 1.8 */ public static Map tryGetFetchGraphHints(EntityManager em, JpaEntityGraph entityGraph, @@ -104,7 +106,65 @@ public class Jpa21Utils { return em.getEntityGraph(jpaEntityGraph.getName()); } catch (Exception ex) { // try to create and dynamically register the entityGraph - return PersistenceProvider.fromEntityManager(em).createDynamicEntityGraph(em, jpaEntityGraph, entityType); + return createDynamicEntityGraph(em, jpaEntityGraph, entityType); + } + } + + /** + * Creates a dynamic {@link EntityGraph} from the given {@link JpaEntityGraph} information. + * + * @param em must not be {@literal null}. + * @param jpaEntityGraph must not be {@literal null}. + * @param entityType must not be {@literal null}. + * @return + * @since 1.9 + */ + private static EntityGraph createDynamicEntityGraph(EntityManager em, JpaEntityGraph jpaEntityGraph, + Class entityType) { + + Assert.notNull(em, "EntityManager must not be null!"); + Assert.notNull(jpaEntityGraph, "JpaEntityGraph must not be null!"); + Assert.notNull(entityType, "Entity type must not be null!"); + Assert.isTrue(jpaEntityGraph.isAdHocEntityGraph(), "The given " + jpaEntityGraph + " is not dynamic!"); + + EntityGraph entityGraph = em.createEntityGraph(entityType); + configureFetchGraphFrom(jpaEntityGraph, entityGraph); + + return entityGraph; + } + + /** + * Configures the given {@link EntityGraph} with the fetch graph information stored in {@link JpaEntityGraph}. + * + * @param jpaEntityGraph + * @param entityGraph + */ + static void configureFetchGraphFrom(JpaEntityGraph jpaEntityGraph, EntityGraph entityGraph) { + + List attributePaths = new ArrayList(jpaEntityGraph.getAttributePaths()); + + // Sort to ensure that the intermediate entity subgraphs are created accordingly. + Collections.sort(attributePaths); + Collections.reverse(attributePaths); + + // We build the entity graph based on the paths with highest depth first + for (String path : attributePaths) { + + // Fast path - just single attribute + if (!path.contains(".")) { + entityGraph.addAttributeNodes(path); + continue; + } + + // We need to build nested sub fetch graphs + String[] pathComponents = StringUtils.delimitedListToStringArray(path, "."); + Subgraph parent = null; + + for (int c = 0; c < pathComponents.length - 1; c++) { + parent = c == 0 ? entityGraph.addSubgraph(pathComponents[c]) : parent.addSubgraph(pathComponents[c]); + } + + parent.addAttributeNodes(pathComponents[pathComponents.length - 1]); } } } diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaEntityGraph.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaEntityGraph.java index 877ceb42a..f442330da 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaEntityGraph.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaEntityGraph.java @@ -16,6 +16,7 @@ package org.springframework.data.jpa.repository.query; import java.util.Arrays; +import java.util.List; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType; @@ -34,7 +35,7 @@ public class JpaEntityGraph { private final String name; private final EntityGraphType type; - private final String[] attributePaths; + private final List attributePaths; /** * Creates an {@link JpaEntityGraph}. @@ -48,11 +49,12 @@ public class JpaEntityGraph { } /** - * Creates an {@link JpaEntityGraph}. + * Creates an {@link JpaEntityGraph} with the given name, {@link EntityGraphType} and attribute paths. * * @param name must not be {@literal null} or empty. * @param type must not be {@literal null}. * @param attributePaths may be {@literal null}. + * @since 1.9 */ public JpaEntityGraph(String name, EntityGraphType type, String[] attributePaths) { @@ -61,7 +63,7 @@ public class JpaEntityGraph { this.name = name; this.type = type; - this.attributePaths = attributePaths == null ? EMPTY_ATTRIBUTE_PATHS : attributePaths; + this.attributePaths = Arrays.asList(attributePaths == null ? EMPTY_ATTRIBUTE_PATHS : attributePaths); } /** @@ -88,7 +90,7 @@ public class JpaEntityGraph { * @return * @since 1.9 */ - public String[] getAttributePaths() { + public List getAttributePaths() { return attributePaths; } @@ -96,9 +98,10 @@ public class JpaEntityGraph { * Return {@literal true} if this {@link JpaEntityGraph} needs to be generated on-the-fly. * * @return + * @since 1.9 */ - public boolean isDynamicEntityGraph() { - return this.attributePaths.length > 0; + public boolean isAdHocEntityGraph() { + return !attributePaths.isEmpty(); } /* @@ -107,7 +110,6 @@ public class JpaEntityGraph { */ @Override public String toString() { - return "JpaEntityGraph [name=" + name + ", type=" + type + ", attributePaths=" + Arrays.toString(attributePaths) - + "]"; + return "JpaEntityGraph [name=" + name + ", type=" + type + ", attributePaths=" + attributePaths.toString() + "]"; } } diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java index 5416a5850..78098a7ef 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2014 the original author or authors. + * Copyright 2008-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,8 +15,7 @@ */ package org.springframework.data.jpa.repository.query; -import static org.springframework.core.annotation.AnnotationUtils.findAnnotation; -import static org.springframework.core.annotation.AnnotationUtils.getAnnotation; +import static org.springframework.core.annotation.AnnotationUtils.*; import java.lang.reflect.Method; import java.util.ArrayList; diff --git a/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadata.java b/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadata.java index 93b915f9f..d99434a1c 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadata.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2014 the original author or authors. + * Copyright 2011-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,6 @@ import java.util.Map; import javax.persistence.LockModeType; import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.query.JpaEntityGraph; /** * Interface to abstract {@link CrudMethodMetadata} that provide the {@link LockModeType} to be used for query @@ -53,7 +52,7 @@ public interface CrudMethodMetadata { * @since 1.9 */ EntityGraph getEntityGraph(); - + /** * Returns the {@link Method} to be used. * diff --git a/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java b/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java index bf4394a5c..6563d34f8 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2014 the original author or authors. + * Copyright 2011-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,10 +34,8 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.Lock; import org.springframework.data.jpa.repository.QueryHints; -import org.springframework.data.jpa.repository.query.JpaEntityGraph; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor; -import org.springframework.data.util.ReflectionUtils; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; @@ -203,16 +201,18 @@ enum CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor { public Map getQueryHints() { return queryHints; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) * @see org.springframework.data.jpa.repository.support.CrudMethodMetadata#getEntityGraph() */ @Override public EntityGraph getEntityGraph() { return entityGraph; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) * @see org.springframework.data.jpa.repository.support.CrudMethodMetadata#getMethod() */ @Override diff --git a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java index 6111a0157..5376c13c1 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java @@ -15,11 +15,7 @@ */ package org.springframework.data.jpa.repository.support; -import static org.springframework.data.jpa.repository.query.QueryUtils.COUNT_QUERY_STRING; -import static org.springframework.data.jpa.repository.query.QueryUtils.DELETE_ALL_QUERY_STRING; -import static org.springframework.data.jpa.repository.query.QueryUtils.applyAndBind; -import static org.springframework.data.jpa.repository.query.QueryUtils.getQueryString; -import static org.springframework.data.jpa.repository.query.QueryUtils.toOrders; +import static org.springframework.data.jpa.repository.query.QueryUtils.*; import java.io.Serializable; import java.util.ArrayList; @@ -260,7 +256,7 @@ public class SimpleJpaRepository implements JpaRepos } private JpaEntityGraph getEntityGraph() { - + String fallbackName = this.entityInformation.getEntityName() + "." + metadata.getMethod().getName(); return new JpaEntityGraph(metadata.getEntityGraph(), fallbackName); } diff --git a/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java b/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java index 24039fca1..fa2327560 100644 --- a/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,37 +15,21 @@ */ package org.springframework.data.jpa.provider; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.springframework.data.jpa.provider.PersistenceProvider.ECLIPSELINK; -import static org.springframework.data.jpa.provider.PersistenceProvider.GENERIC_JPA; -import static org.springframework.data.jpa.provider.PersistenceProvider.HIBERNATE; -import static org.springframework.data.jpa.provider.PersistenceProvider.OPEN_JPA; -import static org.springframework.data.jpa.provider.PersistenceProvider.fromEntityManager; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.ECLIPSELINK_ENTITY_MANAGER_INTERFACE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.HIBERNATE43_ENTITY_MANAGER_INTERFACE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.HIBERNATE_ENTITY_MANAGER_INTERFACE; -import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.OPENJPA_ENTITY_MANAGER_INTERFACE; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.springframework.data.jpa.provider.PersistenceProvider.*; +import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.*; import java.util.ArrayList; import java.util.List; -import javax.persistence.EntityGraph; import javax.persistence.EntityManager; -import javax.persistence.Subgraph; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.asm.ClassWriter; import org.springframework.asm.Opcodes; -import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType; -import org.springframework.data.jpa.repository.query.JpaEntityGraph; import org.springframework.instrument.classloading.ShadowingClassLoader; import org.springframework.util.ClassUtils; @@ -118,26 +102,6 @@ public class PersistenceProviderUnitTests { assertThat(fromEntityManager(em), is(GENERIC_JPA)); } - /** - * @see DATAJPA-696 - */ - @Test - public void shouldBuildCorrectSubgraphForJpaEntityGraph() throws Exception { - - EntityGraph entityGraph = mock(EntityGraph.class); - Subgraph subgraph = mock(Subgraph.class); - doReturn(subgraph).when(entityGraph).addSubgraph(anyString()); - - JpaEntityGraph jpaEntityGraph = new JpaEntityGraph("foo", EntityGraphType.FETCH, - new String[] { "foo", "gugu.gaga" }); - - PersistenceProvider.GENERIC_JPA.configureFetchGraphFrom(jpaEntityGraph, entityGraph); - - verify(entityGraph, times(1)).addAttributeNodes("foo"); - verify(entityGraph, times(1)).addSubgraph("gugu"); - verify(subgraph, times(1)).addAttributeNodes("gaga"); - } - private EntityManager mockProviderSpecificEntityManagerInterface(String interfaceName) throws ClassNotFoundException { Class providerSpecificEntityManagerInterface = InterfaceGenerator.generate(interfaceName, shadowingClassLoader, diff --git a/src/test/java/org/springframework/data/jpa/repository/EntityGraphRepositoryMethodsIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/EntityGraphRepositoryMethodsIntegrationTests.java index bc2ba63d3..143990352 100644 --- a/src/test/java/org/springframework/data/jpa/repository/EntityGraphRepositoryMethodsIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/EntityGraphRepositoryMethodsIntegrationTests.java @@ -31,13 +31,16 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.domain.sample.Role; import org.springframework.data.jpa.domain.sample.User; -import org.springframework.data.jpa.repository.sample.RepositoryMethodsWithEntityGraphConfigJpaRepository; +import org.springframework.data.jpa.repository.sample.RepositoryMethodsWithEntityGraphConfigRepository; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; /** + * Integration tests for RepositoryMethodsWithEntityGraphConfigJpaRepository. + * * @author Thomas Darimont + * @author Oliver Gierke */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:config/namespace-autoconfig-context.xml") @@ -45,25 +48,25 @@ import org.springframework.transaction.annotation.Transactional; public class EntityGraphRepositoryMethodsIntegrationTests { @Autowired EntityManager em; - @Autowired RepositoryMethodsWithEntityGraphConfigJpaRepository repository; + @Autowired RepositoryMethodsWithEntityGraphConfigRepository repository; User tom; - User olli; + User ollie; Role role; @Before public void setup() { tom = new User("Thomas", "Darimont", "tdarimont@example.org"); - olli = new User("Oliver", "Gierke", "ogierke@example.org"); + ollie = new User("Oliver", "Gierke", "ogierke@example.org"); role = new Role("Developer"); em.persist(role); tom.getRoles().add(role); tom = repository.save(tom); - - olli = repository.save(olli); - tom.getColleagues().add(olli); + + ollie = repository.save(ollie); + tom.getColleagues().add(ollie); } /** @@ -95,7 +98,7 @@ public class EntityGraphRepositoryMethodsIntegrationTests { assertThat("colleages should be fetched with 'user.detail' fetchgraph", Persistence.getPersistenceUtil().isLoaded(user.getColleagues()), is(true)); } - + /** * @see DATAJPA-696 */ @@ -110,7 +113,7 @@ public class EntityGraphRepositoryMethodsIntegrationTests { assertThat("colleages should be fetched with 'user.detail' fetchgraph", Persistence.getPersistenceUtil().isLoaded(user.getColleagues()), is(true)); } - + /** * @see DATAJPA-696 */ diff --git a/src/test/java/org/springframework/data/jpa/repository/query/Jpa21UtilsUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/Jpa21UtilsUnitTests.java new file mode 100644 index 000000000..4a7088354 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/query/Jpa21UtilsUnitTests.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.query; + +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import javax.persistence.EntityGraph; +import javax.persistence.Subgraph; + +import org.junit.Test; +import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType; + +/** + * Unit tests for {@link Jpa21Utils}. + * + * @author Thomas Darimont + * @author Oliver Gierke + */ +public class Jpa21UtilsUnitTests { + + /** + * @see DATAJPA-696 + */ + @Test + public void shouldBuildCorrectSubgraphForJpaEntityGraph() throws Exception { + + EntityGraph entityGraph = mock(EntityGraph.class); + Subgraph subgraph = mock(Subgraph.class); + doReturn(subgraph).when(entityGraph).addSubgraph(anyString()); + + JpaEntityGraph jpaEntityGraph = new JpaEntityGraph("foo", EntityGraphType.FETCH, + new String[] { "foo", "gugu.gaga" }); + + Jpa21Utils.configureFetchGraphFrom(jpaEntityGraph, entityGraph); + + verify(entityGraph, times(1)).addAttributeNodes("foo"); + verify(entityGraph, times(1)).addSubgraph("gugu"); + verify(subgraph, times(1)).addAttributeNodes("gaga"); + } +} diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/RepositoryMethodsWithEntityGraphConfigJpaRepository.java b/src/test/java/org/springframework/data/jpa/repository/sample/RepositoryMethodsWithEntityGraphConfigRepository.java similarity index 91% rename from src/test/java/org/springframework/data/jpa/repository/sample/RepositoryMethodsWithEntityGraphConfigJpaRepository.java rename to src/test/java/org/springframework/data/jpa/repository/sample/RepositoryMethodsWithEntityGraphConfigRepository.java index 6b24249e9..a8b264076 100644 --- a/src/test/java/org/springframework/data/jpa/repository/sample/RepositoryMethodsWithEntityGraphConfigJpaRepository.java +++ b/src/test/java/org/springframework/data/jpa/repository/sample/RepositoryMethodsWithEntityGraphConfigRepository.java @@ -21,6 +21,7 @@ import org.springframework.data.jpa.domain.sample.User; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.CrudRepository; /** * Custom repository interface that customizes the fetching behavior of querys of well known repository interface @@ -28,7 +29,7 @@ import org.springframework.data.jpa.repository.JpaRepository; * * @author Thomas Darimont */ -public interface RepositoryMethodsWithEntityGraphConfigJpaRepository extends JpaRepository { +public interface RepositoryMethodsWithEntityGraphConfigRepository extends CrudRepository { /** * Should find all users.