From 633365dfc5dccc7cf351f72a809d02998246a747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Wed, 23 Nov 2016 19:28:12 +0100 Subject: [PATCH 01/81] Compatibility with 1.10.4.RELEASE --- pom.xml | 12 +++++++++--- .../spring/data/jpa/entity/graph/BaseTest.java | 8 ++------ .../entity/graph/DataRepositoryConfiguration.java | 3 +++ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 331d80f..f5bf028 100644 --- a/pom.xml +++ b/pom.xml @@ -6,18 +6,18 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.11.00-SNAPSHOT + 1.10.00-SNAPSHOT 1.6 - 1.11.0.BUILD-SNAPSHOT + 1.10.4.RELEASE 2.6.2 4.1.3 2.5.3 1.3.0 - 1.4.1.RELEASE + 1.3.8.RELEASE

1.4.193

@@ -86,6 +86,12 @@ ${dbunit} test + + org.assertj + assertj-core + 3.3.0 + test + diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/BaseTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/BaseTest.java index ab538bd..86ae4f0 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/BaseTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/BaseTest.java @@ -1,14 +1,11 @@ package com.cosium.spring.data.jpa.entity.graph; import com.github.springtestdbunit.DbUnitTestExecutionListener; -import com.github.springtestdbunit.annotation.DatabaseSetup; -import com.github.springtestdbunit.annotation.DatabaseTearDown; import org.junit.runner.RunWith; -import org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureDataJpa; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import org.springframework.test.context.transaction.TransactionalTestExecutionListener; @@ -20,9 +17,8 @@ */ @TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class, DbUnitTestExecutionListener.class}) -@RunWith(SpringRunner.class) +@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {DataRepositoryConfiguration.class}) -@AutoConfigureDataJpa @DirtiesContext public abstract class BaseTest { diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/DataRepositoryConfiguration.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/DataRepositoryConfiguration.java index ff5108f..f6bf6d4 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/DataRepositoryConfiguration.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/DataRepositoryConfiguration.java @@ -1,6 +1,8 @@ package com.cosium.spring.data.jpa.entity.graph; import com.cosium.spring.data.jpa.entity.graph.repository.support.JpaEntityGraphRepositoryFactoryBean; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -11,6 +13,7 @@ */ @Configuration @EnableJpaRepositories(repositoryFactoryBeanClass = JpaEntityGraphRepositoryFactoryBean.class) +@EnableAutoConfiguration public class DataRepositoryConfiguration { } From 8051f38f32e2e36914284c5250d9335df133f4ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Wed, 23 Nov 2016 19:32:21 +0100 Subject: [PATCH 02/81] Compatibility with 1.10.5.RELEASE --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f5bf028..7a7296b 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 1.6 - 1.10.4.RELEASE + 1.10.5.RELEASE 2.6.2 4.1.3 From 0b9bd2b912a7b59a675f1400f9953ac5ad6779ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Wed, 23 Nov 2016 19:59:51 +0100 Subject: [PATCH 03/81] Rename EntityGraph methods to make them more generic. (cherry picked from commit 398315f) --- .../data/jpa/entity/graph/domain/AbstractEntityGraph.java | 2 +- .../data/jpa/entity/graph/domain/DynamicEntityGraph.java | 4 ++-- .../spring/data/jpa/entity/graph/domain/EntityGraph.java | 6 +++--- .../data/jpa/entity/graph/domain/NamedEntityGraph.java | 4 ++-- .../support/RepositoryMethodEntityGraphExtractor.java | 8 ++++---- .../graph/repository/sample/EntityGraphSpecification.java | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java index 5470609..c7e20e7 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java @@ -19,7 +19,7 @@ public AbstractEntityGraph(EntityGraphType type){ } @Override - public EntityGraphType getType() { + public EntityGraphType getEntityGraphType() { return type; } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/DynamicEntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/DynamicEntityGraph.java index 999c96b..6470cf1 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/DynamicEntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/DynamicEntityGraph.java @@ -22,12 +22,12 @@ public DynamicEntityGraph(EntityGraphType type, List attributePaths){ } @Override - public List getAttributePaths() { + public List getEntityGraphAttributePaths() { return attributePaths; } @Override - public final String getName() { + public final String getEntityGraphName() { return null; } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java index c2c7ae8..eab66f2 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java @@ -12,15 +12,15 @@ public interface EntityGraph { /** * @return The type of the entity graph. Can't be null. */ - EntityGraphType getType(); + EntityGraphType getEntityGraphType(); /** * @return The name to use to retrieve the EntityGraph. May be null or empty */ - String getName(); + String getEntityGraphName(); /** * @return The attribute paths. May be null. */ - List getAttributePaths(); + List getEntityGraphAttributePaths(); } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java index 7e8f790..8b8fbe4 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java @@ -25,12 +25,12 @@ public NamedEntityGraph(String name){ } @Override - public String getName() { + public String getEntityGraphName() { return name; } @Override - public final List getAttributePaths() { + public final List getEntityGraphAttributePaths() { return null; } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index d15b864..5e81350 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -46,10 +46,10 @@ private EntityGraphBean buildEntityGraphBean(EntityGraph entityGraph) { return null; } - Assert.notNull(entityGraph.getType()); + Assert.notNull(entityGraph.getEntityGraphType()); org.springframework.data.jpa.repository.EntityGraph.EntityGraphType type; - switch (entityGraph.getType()) { + switch (entityGraph.getEntityGraphType()) { case FETCH: type = org.springframework.data.jpa.repository.EntityGraph.EntityGraphType.FETCH; break; @@ -60,9 +60,9 @@ private EntityGraphBean buildEntityGraphBean(EntityGraph entityGraph) { throw new RuntimeException("Unknown entity graph type"); } - List attributePaths = entityGraph.getAttributePaths(); + List attributePaths = entityGraph.getEntityGraphAttributePaths(); JpaEntityGraph jpaEntityGraph = new JpaEntityGraph( - StringUtils.hasText(entityGraph.getName()) ? entityGraph.getName() : domainClass.getName() + "-_-_-_-_-_-", + StringUtils.hasText(entityGraph.getEntityGraphName()) ? entityGraph.getEntityGraphName() : domainClass.getName() + "-_-_-_-_-_-", type, attributePaths != null ? attributePaths.toArray(new String[attributePaths.size()]) : null ); diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java index 4b19361..f5944e5 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java @@ -20,17 +20,17 @@ public EntityGraphSpecification(String entityGraphName) { } @Override - public String getName() { + public String getEntityGraphName() { return entityGraphName; } @Override - public EntityGraphType getType() { + public EntityGraphType getEntityGraphType() { return EntityGraphType.FETCH; } @Override - public List getAttributePaths() { + public List getEntityGraphAttributePaths() { return null; } } From 1dfd923a029f03fda947d646a57f5922aae4b171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Wed, 23 Nov 2016 20:22:18 +0100 Subject: [PATCH 04/81] Add the concept of empty Entitygraph (cherry picked from commit 6a2c746) --- .../graph/domain/AbstractEntityGraph.java | 16 +++---- .../jpa/entity/graph/domain/EntityGraph.java | 4 +- .../entity/graph/domain/EntityGraphUtils.java | 47 ++++++++++++++++++- .../RepositoryMethodEntityGraphExtractor.java | 3 +- .../JpaEntityGraphRepositoryTest.java | 8 ++++ 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java index c7e20e7..1342075 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java @@ -9,22 +9,22 @@ */ public abstract class AbstractEntityGraph implements EntityGraph{ - private EntityGraphType type = EntityGraphType.FETCH; + private EntityGraphType entityGraphType = EntityGraphType.FETCH; public AbstractEntityGraph(){} - public AbstractEntityGraph(EntityGraphType type){ - Assert.notNull(type); - this.type = type; + public AbstractEntityGraph(EntityGraphType entityGraphType){ + Assert.notNull(entityGraphType); + this.entityGraphType = entityGraphType; } @Override public EntityGraphType getEntityGraphType() { - return type; + return entityGraphType; } - public void setType(EntityGraphType type) { - Assert.notNull(type); - this.type = type; + public void setEntityGraphType(EntityGraphType entityGraphType) { + Assert.notNull(entityGraphType); + this.entityGraphType = entityGraphType; } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java index eab66f2..420c99c 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java @@ -10,12 +10,12 @@ public interface EntityGraph { /** - * @return The type of the entity graph. Can't be null. + * @return The type of the entity graph. May be null. */ EntityGraphType getEntityGraphType(); /** - * @return The name to use to retrieve the EntityGraph. May be null or empty + * @return The name to use to retrieve the EntityGraph. May be null. */ String getEntityGraphName(); diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java index 660a956..72daab0 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java @@ -1,5 +1,7 @@ package com.cosium.spring.data.jpa.entity.graph.domain; +import java.util.List; + /** * Created on 22/11/16. * @@ -7,8 +9,51 @@ */ public class EntityGraphUtils { - public static EntityGraph fromName(String name){ + private static final EntityGraph EMPTY_ENTITY_GRAPH = new EmptyEntityGraph(); + + /** + * @param entityGraph + * @return True if the provided EntityGraph is empty + */ + public static boolean isEmpty(EntityGraph entityGraph) { + return entityGraph == null || + ( + entityGraph.getEntityGraphAttributePaths() == null + && entityGraph.getEntityGraphName() == null + && entityGraph.getEntityGraphType() == null + ); + } + + /** + * @return An empty EntityGraph + */ + public static EntityGraph empty() { + return EMPTY_ENTITY_GRAPH; + } + + /** + * @param name The name of the targeted EntityGraph + * @return A EntityGraph referenced by name + */ + public static EntityGraph fromName(String name) { return new NamedEntityGraph(name); } + private static final class EmptyEntityGraph implements EntityGraph { + + @Override + public EntityGraphType getEntityGraphType() { + return null; + } + + @Override + public String getEntityGraphName() { + return null; + } + + @Override + public List getEntityGraphAttributePaths() { + return null; + } + } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 5e81350..853485c 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -3,6 +3,7 @@ import java.util.List; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; +import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.ProxyFactory; @@ -42,7 +43,7 @@ private static class JpaEntityGraphMethodInterceptor implements MethodIntercepto } private EntityGraphBean buildEntityGraphBean(EntityGraph entityGraph) { - if (entityGraph == null) { + if(EntityGraphUtils.isEmpty(entityGraph)){ return null; } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index d03b7e3..1d0303f 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -42,6 +42,14 @@ public void given_null_eg_when_findone_then_then_brand_should_not_be_loaded(){ assertThat(Hibernate.isInitialized(product.getBrand())).isFalse(); } + @Transactional + @Test + public void given_empty_eg_when_findone_then_then_brand_should_not_be_loaded(){ + Product product = productRepository.findOne(1L, EntityGraphUtils.empty()); + assertThat(product).isNotNull(); + assertThat(Hibernate.isInitialized(product.getBrand())).isFalse(); + } + @Transactional @Test public void given_brand_eg_when_findone_then_brand_should_be_loaded(){ From cee447854a078df6ca33eac9805bcb80568578ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Wed, 23 Nov 2016 20:40:54 +0100 Subject: [PATCH 05/81] Add test on pagination (cherry picked from commit c9cd9a6) --- .../JpaEntityGraphRepositoryTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index 1d0303f..3349b76 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -19,6 +19,8 @@ import com.github.springtestdbunit.annotation.DatabaseTearDown; import org.hibernate.Hibernate; import org.junit.Test; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.domain.Specification; import org.springframework.transaction.annotation.Transactional; @@ -68,4 +70,30 @@ public void given_brand_eg_when_findByName_then_brand_should_be_loaded(){ } } + @Transactional + @Test + public void given_brand_eg_when_findAll_paginated_then_brand_should_be_loaded(){ + Page productPage = productRepository.findAll(new PageRequest(0, 10), EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + assertThat(productPage.getContent()).isNotEmpty(); + for(Product product: productPage.getContent()){ + assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); + } + } + + @Transactional + @Test + public void given_brand_eg_when_findAll_paginated_with_spec_then_brand_should_be_loaded(){ + Page productPage = productRepository.findAll(new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return null; + } + }, new PageRequest(0, 10)); + + assertThat(productPage.getContent()).isNotEmpty(); + for(Product product: productPage.getContent()){ + assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); + } + } + } \ No newline at end of file From 74adc88c0fc07ca3d2788e99ee8009e5a364641a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Wed, 23 Nov 2016 21:15:49 +0100 Subject: [PATCH 06/81] Error on count query triggered by page query --- ...itoryEntityManagerEntityGraphInjector.java | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java index 3c3507c..db5c8c5 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java @@ -2,6 +2,7 @@ import javax.persistence.EntityManager; import javax.persistence.Query; +import javax.persistence.criteria.CriteriaQuery; import java.util.*; import org.aopalliance.intercept.MethodInterceptor; @@ -44,18 +45,25 @@ static EntityManager proxy(EntityManager entityManager) { public Object invoke(MethodInvocation invocation) throws Throwable { String methodName = invocation.getMethod().getName(); if (FIND_METHODS.contains(methodName)) { - addEntityGraph(invocation); + addEntityGraphToFindMethodQueryHints(invocation); } Object result = invocation.proceed(); if (CREATE_QUERY_METHODS.contains(methodName)) { - addEntityGraph(invocation, (Query) result); + addEntityGraphToCreatedQuery(invocation, (Query) result); } return result; } - private Map getCurrentQueryHints(EntityManager entityManager) { + private EntityGraphBean getCurrentEntitGraph() { EntityGraphBean entityGraphBean = RepositoryMethodEntityGraphExtractor.getCurrentJpaEntityGraph(); if (entityGraphBean == null) { + return null; + } + return entityGraphBean; + } + + private Map getQueryHints(EntityManager entityManager, EntityGraphBean entityGraphBean){ + if(entityGraphBean == null){ return new HashMap(); } return Jpa21Utils.tryGetFetchGraphHints( @@ -71,8 +79,28 @@ private Map getCurrentQueryHints(EntityManager entityManager) { * @param invocation The method invocation * @param query The query to populate */ - private void addEntityGraph(MethodInvocation invocation, Query query) { - Map hints = getCurrentQueryHints((EntityManager) invocation.getThis()); + private void addEntityGraphToCreatedQuery(MethodInvocation invocation, Query query) { + EntityGraphBean currentEntityGraph = getCurrentEntitGraph(); + if(currentEntityGraph == null){ + return; + } + + Class resultType = null; + for(Object argument: invocation.getArguments()){ + if(argument instanceof Class){ + resultType = (Class) argument; + break; + } else if(argument instanceof CriteriaQuery){ + resultType = ((CriteriaQuery) argument).getResultType(); + break; + } + } + + if(resultType != null && !resultType.equals(currentEntityGraph.getDomainClass())){ + return; + } + + Map hints = getQueryHints((EntityManager) invocation.getThis(), currentEntityGraph); for (Map.Entry hint : hints.entrySet()) { query.setHint(hint.getKey(), hint.getValue()); } @@ -83,7 +111,12 @@ private void addEntityGraph(MethodInvocation invocation, Query query) { * * @param invocation The invocation of the find method */ - private void addEntityGraph(MethodInvocation invocation) { + private void addEntityGraphToFindMethodQueryHints(MethodInvocation invocation) { + EntityGraphBean currentEntityGraph = getCurrentEntitGraph(); + if(currentEntityGraph == null){ + return; + } + Map queryProperties = null; int index = 0; for (Object argument : invocation.getArguments()) { @@ -98,7 +131,7 @@ private void addEntityGraph(MethodInvocation invocation) { } queryProperties = new HashMap(queryProperties); - queryProperties.putAll(getCurrentQueryHints((EntityManager) invocation.getThis())); + queryProperties.putAll(getQueryHints((EntityManager) invocation.getThis(), currentEntityGraph)); invocation.getArguments()[index] = queryProperties; } } From 1f4f95764d5cf046091a9f46d3c84bb6e8669da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Wed, 23 Nov 2016 23:31:33 +0100 Subject: [PATCH 07/81] Refactor proxy injector for performance (cherry picked from commit 0f43e1f) --- ...itoryEntityManagerEntityGraphInjector.java | 47 +++++++------------ 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java index db5c8c5..de74e51 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java @@ -43,27 +43,22 @@ static EntityManager proxy(EntityManager entityManager) { @Override public Object invoke(MethodInvocation invocation) throws Throwable { + EntityGraphBean entityGraphBean = RepositoryMethodEntityGraphExtractor.getCurrentJpaEntityGraph(); String methodName = invocation.getMethod().getName(); - if (FIND_METHODS.contains(methodName)) { - addEntityGraphToFindMethodQueryHints(invocation); + if (entityGraphBean != null && FIND_METHODS.contains(methodName)) { + addEntityGraphToFindMethodQueryHints(entityGraphBean, invocation); } + Object result = invocation.proceed(); - if (CREATE_QUERY_METHODS.contains(methodName)) { - addEntityGraphToCreatedQuery(invocation, (Query) result); + + if (entityGraphBean != null && CREATE_QUERY_METHODS.contains(methodName)) { + addEntityGraphToCreatedQuery(entityGraphBean, invocation, (Query) result); } return result; } - private EntityGraphBean getCurrentEntitGraph() { - EntityGraphBean entityGraphBean = RepositoryMethodEntityGraphExtractor.getCurrentJpaEntityGraph(); + private Map getQueryHints(EntityManager entityManager, EntityGraphBean entityGraphBean) { if (entityGraphBean == null) { - return null; - } - return entityGraphBean; - } - - private Map getQueryHints(EntityManager entityManager, EntityGraphBean entityGraphBean){ - if(entityGraphBean == null){ return new HashMap(); } return Jpa21Utils.tryGetFetchGraphHints( @@ -79,28 +74,23 @@ private Map getQueryHints(EntityManager entityManager, EntityGra * @param invocation The method invocation * @param query The query to populate */ - private void addEntityGraphToCreatedQuery(MethodInvocation invocation, Query query) { - EntityGraphBean currentEntityGraph = getCurrentEntitGraph(); - if(currentEntityGraph == null){ - return; - } - + private void addEntityGraphToCreatedQuery(EntityGraphBean entityGraphBean, MethodInvocation invocation, Query query) { Class resultType = null; - for(Object argument: invocation.getArguments()){ - if(argument instanceof Class){ + for (Object argument : invocation.getArguments()) { + if (argument instanceof Class) { resultType = (Class) argument; break; - } else if(argument instanceof CriteriaQuery){ + } else if (argument instanceof CriteriaQuery) { resultType = ((CriteriaQuery) argument).getResultType(); break; } } - if(resultType != null && !resultType.equals(currentEntityGraph.getDomainClass())){ + if (resultType != null && !resultType.equals(entityGraphBean.getDomainClass())) { return; } - Map hints = getQueryHints((EntityManager) invocation.getThis(), currentEntityGraph); + Map hints = getQueryHints((EntityManager) invocation.getThis(), entityGraphBean); for (Map.Entry hint : hints.entrySet()) { query.setHint(hint.getKey(), hint.getValue()); } @@ -111,12 +101,7 @@ private void addEntityGraphToCreatedQuery(MethodInvocation invocation, Query que * * @param invocation The invocation of the find method */ - private void addEntityGraphToFindMethodQueryHints(MethodInvocation invocation) { - EntityGraphBean currentEntityGraph = getCurrentEntitGraph(); - if(currentEntityGraph == null){ - return; - } - + private void addEntityGraphToFindMethodQueryHints(EntityGraphBean entityGraphBean, MethodInvocation invocation) { Map queryProperties = null; int index = 0; for (Object argument : invocation.getArguments()) { @@ -131,7 +116,7 @@ private void addEntityGraphToFindMethodQueryHints(MethodInvocation invocation) { } queryProperties = new HashMap(queryProperties); - queryProperties.putAll(getQueryHints((EntityManager) invocation.getThis(), currentEntityGraph)); + queryProperties.putAll(getQueryHints((EntityManager) invocation.getThis(), entityGraphBean)); invocation.getArguments()[index] = queryProperties; } } From 6bf82dffc597eb1e87881fac1b2c88b5e4e19b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 00:10:32 +0100 Subject: [PATCH 08/81] Refactor (cherry picked from commit dc04907) --- ...itoryEntityManagerEntityGraphInjector.java | 32 +++++++++---------- .../RepositoryMethodEntityGraphExtractor.java | 3 ++ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java index de74e51..6c1d73f 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java @@ -43,38 +43,37 @@ static EntityManager proxy(EntityManager entityManager) { @Override public Object invoke(MethodInvocation invocation) throws Throwable { - EntityGraphBean entityGraphBean = RepositoryMethodEntityGraphExtractor.getCurrentJpaEntityGraph(); + EntityGraphBean entityGraph = RepositoryMethodEntityGraphExtractor.getCurrentJpaEntityGraph(); String methodName = invocation.getMethod().getName(); - if (entityGraphBean != null && FIND_METHODS.contains(methodName)) { - addEntityGraphToFindMethodQueryHints(entityGraphBean, invocation); + boolean hasEntityGraph = entityGraph != null; + if (hasEntityGraph && FIND_METHODS.contains(methodName)) { + addEntityGraphToFindMethodQueryHints(entityGraph, invocation); } Object result = invocation.proceed(); - if (entityGraphBean != null && CREATE_QUERY_METHODS.contains(methodName)) { - addEntityGraphToCreatedQuery(entityGraphBean, invocation, (Query) result); + if (hasEntityGraph && CREATE_QUERY_METHODS.contains(methodName)) { + addEntityGraphToCreatedQuery(entityGraph, invocation, (Query) result); } return result; } - private Map getQueryHints(EntityManager entityManager, EntityGraphBean entityGraphBean) { - if (entityGraphBean == null) { - return new HashMap(); - } + private Map getQueryHints(EntityManager entityManager, EntityGraphBean entityGraph) { return Jpa21Utils.tryGetFetchGraphHints( entityManager, - entityGraphBean.getJpaEntityGraph(), - entityGraphBean.getDomainClass() + entityGraph.getJpaEntityGraph(), + entityGraph.getDomainClass() ); } /** * Push the current entity graph to the created query * + * @param entityGraph The EntityGraph to set * @param invocation The method invocation * @param query The query to populate */ - private void addEntityGraphToCreatedQuery(EntityGraphBean entityGraphBean, MethodInvocation invocation, Query query) { + private void addEntityGraphToCreatedQuery(EntityGraphBean entityGraph, MethodInvocation invocation, Query query) { Class resultType = null; for (Object argument : invocation.getArguments()) { if (argument instanceof Class) { @@ -86,11 +85,11 @@ private void addEntityGraphToCreatedQuery(EntityGraphBean entityGraphBean, Metho } } - if (resultType != null && !resultType.equals(entityGraphBean.getDomainClass())) { + if (resultType != null && !resultType.equals(entityGraph.getDomainClass())) { return; } - Map hints = getQueryHints((EntityManager) invocation.getThis(), entityGraphBean); + Map hints = getQueryHints((EntityManager) invocation.getThis(), entityGraph); for (Map.Entry hint : hints.entrySet()) { query.setHint(hint.getKey(), hint.getValue()); } @@ -99,9 +98,10 @@ private void addEntityGraphToCreatedQuery(EntityGraphBean entityGraphBean, Metho /** * Push the current entity graph to the find method query hints. * + * @param entityGraph The EntityGraph to set * @param invocation The invocation of the find method */ - private void addEntityGraphToFindMethodQueryHints(EntityGraphBean entityGraphBean, MethodInvocation invocation) { + private void addEntityGraphToFindMethodQueryHints(EntityGraphBean entityGraph, MethodInvocation invocation) { Map queryProperties = null; int index = 0; for (Object argument : invocation.getArguments()) { @@ -116,7 +116,7 @@ private void addEntityGraphToFindMethodQueryHints(EntityGraphBean entityGraphBea } queryProperties = new HashMap(queryProperties); - queryProperties.putAll(getQueryHints((EntityManager) invocation.getThis(), entityGraphBean)); + queryProperties.putAll(getQueryHints((EntityManager) invocation.getThis(), entityGraph)); invocation.getArguments()[index] = queryProperties; } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 853485c..f051dd3 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -1,9 +1,12 @@ package com.cosium.spring.data.jpa.entity.graph.repository.support; +import javax.persistence.EntityManager; import java.util.List; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; +import org.aopalliance.intercept.ConstructorInterceptor; +import org.aopalliance.intercept.ConstructorInvocation; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.ProxyFactory; From eb19b6a7a2eaf47dc558494ba9ee5cacc1769a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 00:11:50 +0100 Subject: [PATCH 09/81] Refactor imports (cherry picked from commit 68bd3b2) --- .../repository/support/JpaEntityGraphRepositoryFactory.java | 1 - .../support/RepositoryMethodEntityGraphExtractor.java | 3 --- .../repository/support/SimpleJpaEntityGraphRepository.java | 4 ---- 3 files changed, 8 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/JpaEntityGraphRepositoryFactory.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/JpaEntityGraphRepositoryFactory.java index f835915..d1b9c2b 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/JpaEntityGraphRepositoryFactory.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/JpaEntityGraphRepositoryFactory.java @@ -9,7 +9,6 @@ import java.util.List; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; -import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; import org.springframework.data.querydsl.QueryDslPredicateExecutor; import org.springframework.data.repository.core.RepositoryMetadata; diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index f051dd3..853485c 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -1,12 +1,9 @@ package com.cosium.spring.data.jpa.entity.graph.repository.support; -import javax.persistence.EntityManager; import java.util.List; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; -import org.aopalliance.intercept.ConstructorInterceptor; -import org.aopalliance.intercept.ConstructorInvocation; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.ProxyFactory; diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/SimpleJpaEntityGraphRepository.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/SimpleJpaEntityGraphRepository.java index 1cc430c..098ebeb 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/SimpleJpaEntityGraphRepository.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/SimpleJpaEntityGraphRepository.java @@ -2,9 +2,7 @@ import javax.persistence.EntityManager; import java.io.Serializable; -import java.util.HashMap; import java.util.List; -import java.util.Map; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; import com.cosium.spring.data.jpa.entity.graph.repository.JpaEntityGraphRepository; @@ -14,8 +12,6 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.query.Jpa21Utils; -import org.springframework.data.jpa.repository.query.JpaEntityGraph; import org.springframework.data.jpa.repository.support.JpaEntityInformation; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; From c145b12ccdf2531e2abd2897f82513dadb3a04fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 00:44:08 +0100 Subject: [PATCH 10/81] Add default EntityGraph concept (cherry picked from commit 5a1be38) --- .../JpaEntityGraphRepositoryFactory.java | 2 +- .../RepositoryMethodEntityGraphExtractor.java | 81 ++++++++++++------- .../JpaEntityGraphRepositoryTest.java | 9 ++- .../entity/graph/repository/sample/Maker.java | 34 ++++++++ .../graph/repository/sample/Product.java | 14 ++++ .../spring/data/jpa/entity/graph/dataset.xml | 10 ++- 6 files changed, 116 insertions(+), 34 deletions(-) create mode 100644 src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Maker.java diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/JpaEntityGraphRepositoryFactory.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/JpaEntityGraphRepositoryFactory.java index d1b9c2b..b93f684 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/JpaEntityGraphRepositoryFactory.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/JpaEntityGraphRepositoryFactory.java @@ -61,7 +61,7 @@ private static void addEntityGraphToSpecialTypes(Class clazz, String fieldNam */ public JpaEntityGraphRepositoryFactory(EntityManager entityManager) { super(entityManager); - addRepositoryProxyPostProcessor(new RepositoryMethodEntityGraphExtractor()); + addRepositoryProxyPostProcessor(new RepositoryMethodEntityGraphExtractor(entityManager)); } @Override diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 853485c..7839008 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -1,5 +1,6 @@ package com.cosium.spring.data.jpa.entity.graph.repository.support; +import javax.persistence.EntityManager; import java.util.List; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; @@ -25,9 +26,15 @@ class RepositoryMethodEntityGraphExtractor implements RepositoryProxyPostProcess private static final ThreadLocal CURRENT_ENTITY_GRAPH = new NamedThreadLocal("Thread local holding the current spring data jpa repository entity graph"); + private final EntityManager entityManager; + + RepositoryMethodEntityGraphExtractor(EntityManager entityManager) { + this.entityManager = entityManager; + } + @Override public void postProcess(ProxyFactory factory, RepositoryInformation repositoryInformation) { - factory.addAdvice(new JpaEntityGraphMethodInterceptor(repositoryInformation.getDomainType())); + factory.addAdvice(new JpaEntityGraphMethodInterceptor(entityManager, repositoryInformation.getDomainType())); } static EntityGraphBean getCurrentJpaEntityGraph() { @@ -36,15 +43,56 @@ static EntityGraphBean getCurrentJpaEntityGraph() { private static class JpaEntityGraphMethodInterceptor implements MethodInterceptor { - private final Class domainClass; + private static final String DEFAULT_ENTITYGRAPH_NAME_SUFFIX = ".default"; + private final Class domainClass; + private final EntityGraphBean defaultEntityGraph; - JpaEntityGraphMethodInterceptor(Class domainClass) { + JpaEntityGraphMethodInterceptor(EntityManager entityManager, Class domainClass) { this.domainClass = domainClass; + this.defaultEntityGraph = findDefaultEntityGraph(entityManager); + } + + /** + * @param entityManager + * @return The default entity graph if it exists. Null otherwise. + */ + private EntityGraphBean findDefaultEntityGraph(EntityManager entityManager){ + List> entityGraphs = entityManager.getEntityGraphs(domainClass); + for (javax.persistence.EntityGraph entityGraph : entityGraphs) { + if (entityGraph.getName().endsWith(DEFAULT_ENTITYGRAPH_NAME_SUFFIX)) { + return buildEntityGraphBean(EntityGraphUtils.fromName(entityGraph.getName())); + } + } + return null; + } + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + Object[] arguments = invocation.getArguments(); + EntityGraph entityGraph = null; + for (Object argument : arguments) { + if (!(argument instanceof EntityGraph)) { + continue; + } + entityGraph = (EntityGraph) argument; + break; + } + EntityGraphBean entityGraphBean = buildEntityGraphBean(entityGraph); + if (entityGraphBean != null) { + CURRENT_ENTITY_GRAPH.set(entityGraphBean); + } + try { + return invocation.proceed(); + } finally { + if (entityGraphBean != null) { + CURRENT_ENTITY_GRAPH.remove(); + } + } } private EntityGraphBean buildEntityGraphBean(EntityGraph entityGraph) { - if(EntityGraphUtils.isEmpty(entityGraph)){ - return null; + if (EntityGraphUtils.isEmpty(entityGraph)) { + return defaultEntityGraph; } Assert.notNull(entityGraph.getEntityGraphType()); @@ -71,28 +119,5 @@ private EntityGraphBean buildEntityGraphBean(EntityGraph entityGraph) { return new EntityGraphBean(jpaEntityGraph, domainClass); } - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - EntityGraph entityGraph = null; - for (Object argument : arguments) { - if (!(argument instanceof EntityGraph)) { - continue; - } - entityGraph = (EntityGraph) argument; - break; - } - EntityGraphBean entityGraphBean = buildEntityGraphBean(entityGraph); - if (entityGraphBean != null) { - CURRENT_ENTITY_GRAPH.set(entityGraphBean); - } - try { - return invocation.proceed(); - } finally { - if (entityGraphBean != null) { - CURRENT_ENTITY_GRAPH.remove(); - } - } - } } } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index 3349b76..a9e0947 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -21,7 +21,6 @@ import org.junit.Test; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.data.jpa.domain.Specification; import org.springframework.transaction.annotation.Transactional; /** @@ -96,4 +95,12 @@ public Predicate toPredicate(Root root, CriteriaQuery query, Criteri } } + @Transactional + @Test + public void given_default_eg_when_findone_without_eg_then_supplier_should_be_loaded(){ + Product product = productRepository.findOne(1L); + assertThat(product).isNotNull(); + assertThat(Hibernate.isInitialized(product.getMaker())).isTrue(); + } + } \ No newline at end of file diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Maker.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Maker.java new file mode 100644 index 0000000..3cf877a --- /dev/null +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Maker.java @@ -0,0 +1,34 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.sample; + +import javax.persistence.*; + +/** + * Created on 24/11/16. + * + * @author Reda.Housni-Alaoui + */ +@Entity +public class Maker { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Access(value = AccessType.PROPERTY) + private long id = 0; + + private String name; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java index 7d66d23..e88493a 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java @@ -8,6 +8,9 @@ * @author Reda.Housni-Alaoui */ @NamedEntityGraphs(value = { + @NamedEntityGraph(name = "Product.default", attributeNodes = { + @NamedAttributeNode("maker") + }), @NamedEntityGraph(name = Product.PRODUCT_BRAND_EG, attributeNodes = { @NamedAttributeNode("brand") }) @@ -27,6 +30,9 @@ public class Product { @ManyToOne(fetch = FetchType.LAZY) private Brand brand; + @ManyToOne(fetch = FetchType.LAZY) + private Maker maker; + public long getId() { return id; } @@ -50,4 +56,12 @@ public Brand getBrand() { public void setBrand(Brand brand) { this.brand = brand; } + + public Maker getMaker() { + return maker; + } + + public void setMaker(Maker maker) { + this.maker = maker; + } } diff --git a/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml b/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml index 2c0be0f..3a905bb 100644 --- a/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml +++ b/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml @@ -3,8 +3,10 @@ - - - - + + + + + + \ No newline at end of file From 6a983af9efd582a756fb8ed63fe7907c1ad81e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 00:58:40 +0100 Subject: [PATCH 11/81] Complete README --- README.md | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0978adb..71854c3 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Thus, for a method, the choice of EntityGraph must be made before compilation. This library gives the ability to pass EntityGraph on any Spring Data JPA repository method as an argument, making the EntityGraph choice fully dynamic. -### Quick start in 3 steps +### Quick start 1. Add the dependency : @@ -27,7 +27,7 @@ This library gives the ability to pass EntityGraph on any Spring Data JPA reposi ``` 3. Make sure your repositories extend `JpaEntityGraphRepository`, `JpaEntityGraphSpecificationExecutor` and/or `JpaEntityGraphQueryDslPredicateExecutor` -### Usage +### Basic Usage Let's consider the following entities and repository : ```java @@ -63,14 +63,42 @@ public interface ProductRepository extends JpaEntityGraphRepository Date: Thu, 24 Nov 2016 01:03:33 +0100 Subject: [PATCH 12/81] Add unique constraint on default method (cherry picked from commit a3ef93d) --- .../support/RepositoryMethodEntityGraphExtractor.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 7839008..972c92d 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -57,13 +57,17 @@ private static class JpaEntityGraphMethodInterceptor implements MethodIntercepto * @return The default entity graph if it exists. Null otherwise. */ private EntityGraphBean findDefaultEntityGraph(EntityManager entityManager){ + EntityGraphBean entityGraphBean = null; List> entityGraphs = entityManager.getEntityGraphs(domainClass); for (javax.persistence.EntityGraph entityGraph : entityGraphs) { if (entityGraph.getName().endsWith(DEFAULT_ENTITYGRAPH_NAME_SUFFIX)) { - return buildEntityGraphBean(EntityGraphUtils.fromName(entityGraph.getName())); + if(entityGraphBean != null){ + throw new RuntimeException("Multiple default entity graphs detected : " + entityGraph.getName() + " and " + entityGraphBean.getJpaEntityGraph().getName()); + } + entityGraphBean = buildEntityGraphBean(EntityGraphUtils.fromName(entityGraph.getName())); } } - return null; + return entityGraphBean; } @Override From 9faae0d99f8bbe154ef7447264bbbb76adb4ef40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 01:07:11 +0100 Subject: [PATCH 13/81] Change version in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 71854c3..88624fe 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ This library gives the ability to pass EntityGraph on any Spring Data JPA reposi com.cosium.spring.data spring-data-jpa-entity-graph - 1.11.00-SNAPSHOT + 1.10.00 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From 14891e393c802696858b57c70194c07a74de52eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 01:14:44 +0100 Subject: [PATCH 14/81] Add compatibility table (cherry picked from commit 3b64538) --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 88624fe..b0ed7f3 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,18 @@ Thus, for a method, the choice of EntityGraph must be made before compilation. This library gives the ability to pass EntityGraph on any Spring Data JPA repository method as an argument, making the EntityGraph choice fully dynamic. +### Spring Data JPA Compatibility + +This library follows the Spring Data JPA versionning semantic. + +spring-data-jpa-entity-graph | spring-data-jpa +---------------------------- | --------------- +1.11.x | 1.11.y +1.10.x | 1.10.y + ### Quick start -1. Add the dependency : +1. In addition to spring-data-jpa, add the library dependency : ```xml From dcb9d9365a88583a30b4b8d58513da9b9a318015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 01:18:11 +0100 Subject: [PATCH 15/81] Add scm (cherry picked from commit 536ce8e) --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index 7a7296b..792dfa5 100644 --- a/pom.xml +++ b/pom.xml @@ -215,4 +215,10 @@ + + scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph + scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph + https://github.com/Cosium/spring-data-jpa-entity-graph + + \ No newline at end of file From 5bb8f29df87d3ecf9da31664881820e6e2bb1d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 01:18:53 +0100 Subject: [PATCH 16/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.00 --- pom.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 792dfa5..cfd7a8c 100644 --- a/pom.xml +++ b/pom.xml @@ -1,12 +1,10 @@ - + 4.0.0 com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.00-SNAPSHOT + 1.10.00 1.6 @@ -219,6 +217,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - + spring-data-jpa-entity-graph-1.10.00 + \ No newline at end of file From 1cbe51831bd2356ff5da86c19799ca7a2adcd6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 01:18:53 +0100 Subject: [PATCH 17/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cfd7a8c..a56614c 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.00 + 1.10.01-SNAPSHOT 1.6 @@ -217,7 +217,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.00 + HEAD \ No newline at end of file From 1be969c6067ea345d7c3b5ac88200ba27441d571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 17:07:40 +0100 Subject: [PATCH 18/81] @EntityGraph must not be overridden by the default EntityGraph (cherry picked from commit 0d8aacc) --- .../entity/graph/domain/EntityGraphUtils.java | 13 ---- .../repository/support/EntityGraphBean.java | 11 +++- .../repository/support/QueryHintsUtils.java | 44 +++++++++++++ ...itoryEntityManagerEntityGraphInjector.java | 63 ++++++++---------- .../RepositoryMethodEntityGraphExtractor.java | 25 +++++--- .../RepositoryQueryEntityGraphInjector.java | 64 +++++++++++++++++++ .../JpaEntityGraphRepositoryTest.java | 8 +++ .../graph/repository/sample/Product.java | 10 +++ .../repository/sample/ProductRepository.java | 2 + .../spring/data/jpa/entity/graph/dataset.xml | 8 +-- 10 files changed, 187 insertions(+), 61 deletions(-) create mode 100644 src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java create mode 100644 src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java index 72daab0..bda603c 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java @@ -11,19 +11,6 @@ public class EntityGraphUtils { private static final EntityGraph EMPTY_ENTITY_GRAPH = new EmptyEntityGraph(); - /** - * @param entityGraph - * @return True if the provided EntityGraph is empty - */ - public static boolean isEmpty(EntityGraph entityGraph) { - return entityGraph == null || - ( - entityGraph.getEntityGraphAttributePaths() == null - && entityGraph.getEntityGraphName() == null - && entityGraph.getEntityGraphType() == null - ); - } - /** * @return An empty EntityGraph */ diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java index 4a5cbb0..1236200 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java @@ -13,13 +13,15 @@ class EntityGraphBean { private final JpaEntityGraph jpaEntityGraph; private final Class domainClass; + private final boolean optional; - public EntityGraphBean(JpaEntityGraph jpaEntityGraph, Class domainClass) { + public EntityGraphBean(JpaEntityGraph jpaEntityGraph, Class domainClass, boolean optional) { Assert.notNull(jpaEntityGraph); Assert.notNull(domainClass); this.jpaEntityGraph = jpaEntityGraph; this.domainClass = domainClass; + this.optional = optional; } /** @@ -35,4 +37,11 @@ public JpaEntityGraph getJpaEntityGraph() { public Class getDomainClass() { return domainClass; } + + /** + * @return True if this entity graph is not mandatory + */ + public boolean isOptional() { + return optional; + } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java new file mode 100644 index 0000000..c4c1f46 --- /dev/null +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java @@ -0,0 +1,44 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.support; + +import javax.persistence.EntityManager; +import java.util.Map; + +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.query.Jpa21Utils; + +/** + * Created on 24/11/16. + * + * @author Reda.Housni-Alaoui + */ +class QueryHintsUtils { + /** + * @param queryHints + * @return True if the QueryHints already hold an EntityGraph + */ + static boolean containsEntityGraph(Map queryHints){ + return queryHints.containsKey(EntityGraph.EntityGraphType.FETCH.getKey()) + || queryHints.containsKey(EntityGraph.EntityGraphType.LOAD.getKey()); + } + + /** + * Remove all EntityGraph pre existing in the QueryHints + * @param queryHints + */ + static void removeEntityGraphs(Map queryHints){ + if(queryHints == null){ + return; + } + queryHints.remove(EntityGraph.EntityGraphType.FETCH.getKey()); + queryHints.remove(EntityGraph.EntityGraphType.LOAD.getKey()); + } + + + static Map buildQueryHints(EntityManager entityManager, EntityGraphBean entityGraph) { + return Jpa21Utils.tryGetFetchGraphHints( + entityManager, + entityGraph.getJpaEntityGraph(), + entityGraph.getDomainClass() + ); + } +} diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java index 6c1d73f..a2b36b3 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java @@ -7,8 +7,9 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.aop.framework.ProxyFactory; -import org.springframework.data.jpa.repository.query.Jpa21Utils; /** * Injects captured {@link org.springframework.data.jpa.repository.query.JpaEntityGraph} into query hints.
@@ -20,6 +21,8 @@ */ class RepositoryEntityManagerEntityGraphInjector implements MethodInterceptor { + private static final Logger LOG = LoggerFactory.getLogger(RepositoryEntityManagerEntityGraphInjector.class); + /** * The list of methods that can take a map of query hints as an argument */ @@ -29,6 +32,9 @@ class RepositoryEntityManagerEntityGraphInjector implements MethodInterceptor { */ private static final List CREATE_QUERY_METHODS = Arrays.asList("createQuery", "createNamedQuery"); + private RepositoryEntityManagerEntityGraphInjector() { + } + /** * Builds a proxy on entity manager which is aware of methods that can make use of query hints. * @@ -43,37 +49,24 @@ static EntityManager proxy(EntityManager entityManager) { @Override public Object invoke(MethodInvocation invocation) throws Throwable { - EntityGraphBean entityGraph = RepositoryMethodEntityGraphExtractor.getCurrentJpaEntityGraph(); + EntityGraphBean entityGraphCandidate = RepositoryMethodEntityGraphExtractor.getCurrentJpaEntityGraph(); String methodName = invocation.getMethod().getName(); - boolean hasEntityGraph = entityGraph != null; - if (hasEntityGraph && FIND_METHODS.contains(methodName)) { - addEntityGraphToFindMethodQueryHints(entityGraph, invocation); + boolean hasEntityGraphCandidate = entityGraphCandidate != null; + if (hasEntityGraphCandidate && FIND_METHODS.contains(methodName)) { + addEntityGraphToFindMethodQueryHints(entityGraphCandidate, invocation); } Object result = invocation.proceed(); - if (hasEntityGraph && CREATE_QUERY_METHODS.contains(methodName)) { - addEntityGraphToCreatedQuery(entityGraph, invocation, (Query) result); + if (hasEntityGraphCandidate + && CREATE_QUERY_METHODS.contains(methodName) + && isQueryCreationEligible(entityGraphCandidate, invocation)) { + result = RepositoryQueryEntityGraphInjector.proxy((Query) result, (EntityManager) invocation.getThis(), entityGraphCandidate); } return result; } - private Map getQueryHints(EntityManager entityManager, EntityGraphBean entityGraph) { - return Jpa21Utils.tryGetFetchGraphHints( - entityManager, - entityGraph.getJpaEntityGraph(), - entityGraph.getDomainClass() - ); - } - - /** - * Push the current entity graph to the created query - * - * @param entityGraph The EntityGraph to set - * @param invocation The method invocation - * @param query The query to populate - */ - private void addEntityGraphToCreatedQuery(EntityGraphBean entityGraph, MethodInvocation invocation, Query query) { + private boolean isQueryCreationEligible(EntityGraphBean entityGraphCandidate, MethodInvocation invocation) { Class resultType = null; for (Object argument : invocation.getArguments()) { if (argument instanceof Class) { @@ -84,24 +77,18 @@ private void addEntityGraphToCreatedQuery(EntityGraphBean entityGraph, MethodInv break; } } - - if (resultType != null && !resultType.equals(entityGraph.getDomainClass())) { - return; - } - - Map hints = getQueryHints((EntityManager) invocation.getThis(), entityGraph); - for (Map.Entry hint : hints.entrySet()) { - query.setHint(hint.getKey(), hint.getValue()); - } + return resultType == null || resultType.equals(entityGraphCandidate.getDomainClass()); } /** * Push the current entity graph to the find method query hints. * - * @param entityGraph The EntityGraph to set + * @param entityGraphCandidate The EntityGraph to set * @param invocation The invocation of the find method */ - private void addEntityGraphToFindMethodQueryHints(EntityGraphBean entityGraph, MethodInvocation invocation) { + private void addEntityGraphToFindMethodQueryHints(EntityGraphBean entityGraphCandidate, MethodInvocation invocation) { + LOG.trace("Trying to push the EntityGraph candidate to the query hints find method"); + Map queryProperties = null; int index = 0; for (Object argument : invocation.getArguments()) { @@ -112,11 +99,17 @@ private void addEntityGraphToFindMethodQueryHints(EntityGraphBean entityGraph, M index++; } if (queryProperties == null) { + LOG.trace("No query hints passed to the find method."); + return; + } + if (entityGraphCandidate.isOptional() && QueryHintsUtils.containsEntityGraph(queryProperties)) { + LOG.trace("The query hints passed with the find method already hold an entity graph. Overriding aborted because the candidate EntityGraph is optional."); return; } queryProperties = new HashMap(queryProperties); - queryProperties.putAll(getQueryHints((EntityManager) invocation.getThis(), entityGraph)); + QueryHintsUtils.removeEntityGraphs(queryProperties); + queryProperties.putAll(QueryHintsUtils.buildQueryHints((EntityManager) invocation.getThis(), entityGraphCandidate)); invocation.getArguments()[index] = queryProperties; } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 972c92d..29f3ecf 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -41,6 +41,19 @@ static EntityGraphBean getCurrentJpaEntityGraph() { return CURRENT_ENTITY_GRAPH.get(); } + /** + * @param entityGraph + * @return True if the provided EntityGraph is empty + */ + private static boolean isEmpty(EntityGraph entityGraph) { + return entityGraph == null || + ( + entityGraph.getEntityGraphAttributePaths() == null + && entityGraph.getEntityGraphName() == null + && entityGraph.getEntityGraphType() == null + ); + } + private static class JpaEntityGraphMethodInterceptor implements MethodInterceptor { private static final String DEFAULT_ENTITYGRAPH_NAME_SUFFIX = ".default"; @@ -64,7 +77,7 @@ private EntityGraphBean findDefaultEntityGraph(EntityManager entityManager){ if(entityGraphBean != null){ throw new RuntimeException("Multiple default entity graphs detected : " + entityGraph.getName() + " and " + entityGraphBean.getJpaEntityGraph().getName()); } - entityGraphBean = buildEntityGraphBean(EntityGraphUtils.fromName(entityGraph.getName())); + entityGraphBean = buildEntityGraphBean(EntityGraphUtils.fromName(entityGraph.getName()), true); } } return entityGraphBean; @@ -81,7 +94,7 @@ public Object invoke(MethodInvocation invocation) throws Throwable { entityGraph = (EntityGraph) argument; break; } - EntityGraphBean entityGraphBean = buildEntityGraphBean(entityGraph); + EntityGraphBean entityGraphBean = isEmpty(entityGraph)? defaultEntityGraph : buildEntityGraphBean(entityGraph, false); if (entityGraphBean != null) { CURRENT_ENTITY_GRAPH.set(entityGraphBean); } @@ -94,11 +107,7 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } } - private EntityGraphBean buildEntityGraphBean(EntityGraph entityGraph) { - if (EntityGraphUtils.isEmpty(entityGraph)) { - return defaultEntityGraph; - } - + private EntityGraphBean buildEntityGraphBean(EntityGraph entityGraph, boolean optional) { Assert.notNull(entityGraph.getEntityGraphType()); org.springframework.data.jpa.repository.EntityGraph.EntityGraphType type; @@ -120,7 +129,7 @@ private EntityGraphBean buildEntityGraphBean(EntityGraph entityGraph) { attributePaths != null ? attributePaths.toArray(new String[attributePaths.size()]) : null ); - return new EntityGraphBean(jpaEntityGraph, domainClass); + return new EntityGraphBean(jpaEntityGraph, domainClass, optional); } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java new file mode 100644 index 0000000..e431c8e --- /dev/null +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java @@ -0,0 +1,64 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.support; + +import javax.persistence.EntityManager; +import javax.persistence.Query; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.util.Assert; + +/** + * Created on 24/11/16. + * + * @author Reda.Housni-Alaoui + */ +class RepositoryQueryEntityGraphInjector implements MethodInterceptor { + + private static final Logger LOG = LoggerFactory.getLogger(RepositoryQueryEntityGraphInjector.class); + + private static final List EXECUTE_QUERY_METHODS = Arrays.asList("getResultList", "getSingleResult"); + + private final EntityManager entityManager; + private final EntityGraphBean entityGraphCandidate; + + private RepositoryQueryEntityGraphInjector(EntityManager entityManager, EntityGraphBean entityGraphCandidate){ + Assert.notNull(entityManager); + Assert.notNull(entityGraphCandidate); + this.entityManager = entityManager; + this.entityGraphCandidate = entityGraphCandidate; + } + + static Query proxy(Query query, EntityManager entityManager, EntityGraphBean entityGraphCandidate){ + ProxyFactory proxyFactory = new ProxyFactory(query); + proxyFactory.addAdvice(new RepositoryQueryEntityGraphInjector(entityManager, entityGraphCandidate)); + return (Query) proxyFactory.getProxy(); + } + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + if(EXECUTE_QUERY_METHODS.contains(invocation.getMethod().getName())){ + addEntityGraphToQuery((Query) invocation.getThis()); + } + return invocation.proceed(); + } + + private void addEntityGraphToQuery(Query query){ + if(entityGraphCandidate.isOptional() && QueryHintsUtils.containsEntityGraph(query.getHints())){ + LOG.trace("The query hints passed with the find method already hold an entity graph. Overriding aborted because the candidate EntityGraph is optional."); + return; + } + QueryHintsUtils.removeEntityGraphs(query.getHints()); + Map hints = QueryHintsUtils.buildQueryHints(entityManager, entityGraphCandidate); + for (Map.Entry hint : hints.entrySet()) { + query.setHint(hint.getKey(), hint.getValue()); + } + } + +} diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index a9e0947..a0962b7 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -103,4 +103,12 @@ public void given_default_eg_when_findone_without_eg_then_supplier_should_be_loa assertThat(Hibernate.isInitialized(product.getMaker())).isTrue(); } + @Transactional + @Test + public void given_default_eg_when_findByBarcode_with_eg_annotation_on_brand_eg_then_brand_should_be_loaded(){ + Product product = productRepository.findByBarcode("1111"); + assertThat(product).isNotNull(); + assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); + } + } \ No newline at end of file diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java index e88493a..efa4261 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java @@ -27,6 +27,8 @@ public class Product { private String name; + private String barcode; + @ManyToOne(fetch = FetchType.LAZY) private Brand brand; @@ -64,4 +66,12 @@ public Maker getMaker() { public void setMaker(Maker maker) { this.maker = maker; } + + public String getBarcode() { + return barcode; + } + + public void setBarcode(String barcode) { + this.barcode = barcode; + } } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java index 02ec554..6750bd3 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java @@ -19,4 +19,6 @@ public interface ProductRepository List findByName(String name, EntityGraph entityGraph); + @org.springframework.data.jpa.repository.EntityGraph(value = Product.PRODUCT_BRAND_EG) + Product findByBarcode(String barcode); } diff --git a/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml b/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml index 3a905bb..36d891e 100644 --- a/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml +++ b/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml @@ -5,8 +5,8 @@ - - - - + + + + \ No newline at end of file From eea50799b8dc9c5dee6cce6e8749d22efa3ec0ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 17:08:47 +0100 Subject: [PATCH 19/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.01 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a56614c..9667490 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.01-SNAPSHOT + 1.10.01 1.6 @@ -217,7 +217,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.01 \ No newline at end of file From 648f5cc5c78515bbab705b65d30138c4f7464445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 17:08:47 +0100 Subject: [PATCH 20/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9667490..1265c8f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.01 + 1.10.02-SNAPSHOT 1.6 @@ -217,7 +217,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.01 + HEAD \ No newline at end of file From 626c147cb8b0183eea58a698980fd53826358c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 18:55:34 +0100 Subject: [PATCH 21/81] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b0ed7f3..e7af3eb 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.00 + 1.10.01 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From 72faee87e32315387a8bf6a1585f4b0e146abf8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 19:02:21 +0100 Subject: [PATCH 22/81] Add license info (cherry picked from commit 689257f) --- pom.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pom.xml b/pom.xml index 1265c8f..c86f6e4 100644 --- a/pom.xml +++ b/pom.xml @@ -220,4 +220,12 @@ HEAD + + + MIT License + http://www.opensource.org/licenses/mit-license.php + repo + + + \ No newline at end of file From 4adab2fc2a1149c5d1e3c467bead050a2d27e7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 19:11:02 +0100 Subject: [PATCH 23/81] Only gpg sign on release (cherry picked from commit 96e7f06) --- pom.xml | 72 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index c86f6e4..dd11774 100644 --- a/pom.xml +++ b/pom.xml @@ -150,7 +150,7 @@ false true true - false + true release deploy @@ -171,36 +171,38 @@ - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - - sign-artifacts - deploy - - sign - - - -
- - Cosium - http://www.cosium.com - - - - - reda-alaoui - Réda Housni Alaoui - reda.housnialaoui@cosium.com - https://github.com/reda-alaoui - - + + + release-sign-artifacts + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + + @@ -220,6 +222,20 @@ HEAD + + Cosium + http://www.cosium.com + + + + + reda-alaoui + Réda Housni Alaoui + reda.housnialaoui@cosium.com + https://github.com/reda-alaoui + + + MIT License From 7105cb0e316d179c659ba271619941541e8e01b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 19:12:24 +0100 Subject: [PATCH 24/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.02 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index dd11774..1623c57 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.02-SNAPSHOT + 1.10.02 1.6 @@ -219,7 +219,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.02 From d4dc003b7c819a9726901f66842eecf72dab2dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 19:12:24 +0100 Subject: [PATCH 25/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1623c57..8c498a4 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.02 + 1.10.03-SNAPSHOT 1.6 @@ -219,7 +219,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.02 + HEAD From 5e0e66792f0c72d9b56ba56b5858ba624808b4ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 19:18:11 +0100 Subject: [PATCH 26/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.03 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8c498a4..d885e64 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.03-SNAPSHOT + 1.10.03 1.6 @@ -219,7 +219,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.03 From 1170398f099ddd565a1b3f176395fc51f3e6fea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 19:18:11 +0100 Subject: [PATCH 27/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d885e64..cf761a4 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.03 + 1.10.04-SNAPSHOT 1.6 @@ -219,7 +219,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.03 + HEAD From 3571ebe7f4eff990d9505b0355239866bd837d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 19:21:42 +0100 Subject: [PATCH 28/81] Add name, description and url to the pom (cherry picked from commit f08eada) --- pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pom.xml b/pom.xml index cf761a4..5bb00b7 100644 --- a/pom.xml +++ b/pom.xml @@ -2,6 +2,10 @@ 4.0.0 + Spring Data JPA EntityGraph + A Spring Data JPA extension allowing full usage of JPA EntityGraph on repositories + https://github.com/Cosium/spring-data-jpa-entity-graph + com.cosium.spring.data spring-data-jpa-entity-graph 1.10.04-SNAPSHOT From cd4ce4a35ffedc021080bb5bc38db9c49dc9327e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 19:31:00 +0100 Subject: [PATCH 29/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.04 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5bb00b7..404e3fc 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.04-SNAPSHOT + 1.10.04 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.04 From fe0a5ae93a488b72239c88449b95361aef5fb656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 19:31:00 +0100 Subject: [PATCH 30/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 404e3fc..ebe1918 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.04 + 1.10.05-SNAPSHOT 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.04 + HEAD From f508ee061a2248153dc1a68d6ae97194ec139f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 19:32:55 +0100 Subject: [PATCH 31/81] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e7af3eb..a887f3e 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.01 + 1.10.04 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From e8acdf00384e683f6e31f28476a234203231b65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 20:57:28 +0100 Subject: [PATCH 32/81] QueryHints can be null (cherry picked from commit 2fa30eb) --- .../entity/graph/repository/support/QueryHintsUtils.java | 3 ++- .../graph/repository/JpaEntityGraphRepositoryTest.java | 6 ++++++ .../entity/graph/repository/sample/ProductRepository.java | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java index c4c1f46..5bbeebd 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java @@ -17,7 +17,8 @@ class QueryHintsUtils { * @return True if the QueryHints already hold an EntityGraph */ static boolean containsEntityGraph(Map queryHints){ - return queryHints.containsKey(EntityGraph.EntityGraphType.FETCH.getKey()) + return queryHints == null + || queryHints.containsKey(EntityGraph.EntityGraphType.FETCH.getKey()) || queryHints.containsKey(EntityGraph.EntityGraphType.LOAD.getKey()); } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index a0962b7..b218ac2 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -111,4 +111,10 @@ public void given_default_eg_when_findByBarcode_with_eg_annotation_on_brand_eg_t assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); } + @Transactional + @Test + public void given_products_when_countproductsbyname_then_it_should_work(){ + productRepository.countByName("Product 1"); + } + } \ No newline at end of file diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java index 6750bd3..06ef407 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java @@ -21,4 +21,6 @@ public interface ProductRepository @org.springframework.data.jpa.repository.EntityGraph(value = Product.PRODUCT_BRAND_EG) Product findByBarcode(String barcode); + + long countByName(String name); } From bb5dd4ff245af7a284f30d98e1789421d9a40e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 20:58:58 +0100 Subject: [PATCH 33/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.05 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ebe1918..2677ef5 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.05-SNAPSHOT + 1.10.05 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.05 From fa816e0f750a6e587da353cd58f5813985afff39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 20:58:58 +0100 Subject: [PATCH 34/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2677ef5..c08e764 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.05 + 1.10.06-SNAPSHOT 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.05 + HEAD From eb5c6521a4420c5afffda73e7d3100a3e276c5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 21:01:25 +0100 Subject: [PATCH 35/81] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a887f3e..a0c173f 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.04 + 1.10.05 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From d97cb504689d8b1d15af54ee94484ab86d94c688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 23:09:08 +0100 Subject: [PATCH 36/81] Manage raw returns (cherry picked from commit 365eb88) --- .../graph/domain/AbstractEntityGraph.java | 9 ++++ .../graph/domain/DynamicEntityGraph.java | 10 ++++ .../entity/graph/domain/NamedEntityGraph.java | 7 +++ .../repository/support/EntityGraphBean.java | 34 ++++++++++++- ...itoryEntityManagerEntityGraphInjector.java | 1 + .../RepositoryMethodEntityGraphExtractor.java | 48 ++++++++++++------- .../RepositoryQueryEntityGraphInjector.java | 21 +++++--- .../JpaEntityGraphRepositoryTest.java | 6 +++ .../repository/sample/ProductRepository.java | 4 ++ 9 files changed, 115 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java index 1342075..e9b1f2d 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java @@ -1,5 +1,6 @@ package com.cosium.spring.data.jpa.entity.graph.domain; +import com.google.common.base.MoreObjects; import org.springframework.util.Assert; /** @@ -27,4 +28,12 @@ public void setEntityGraphType(EntityGraphType entityGraphType) { Assert.notNull(entityGraphType); this.entityGraphType = entityGraphType; } + + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("entityGraphType", entityGraphType) + .toString(); + } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/DynamicEntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/DynamicEntityGraph.java index 6470cf1..737f49c 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/DynamicEntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/DynamicEntityGraph.java @@ -3,6 +3,8 @@ import java.util.Collections; import java.util.List; +import com.google.common.base.MoreObjects; + /** * Created on 22/11/16. * @@ -30,4 +32,12 @@ public List getEntityGraphAttributePaths() { public final String getEntityGraphName() { return null; } + + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("attributePaths", attributePaths) + .toString(); + } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java index 8b8fbe4..4a5d820 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java @@ -2,6 +2,7 @@ import java.util.List; +import com.google.common.base.MoreObjects; import org.springframework.util.Assert; /** @@ -34,4 +35,10 @@ public final List getEntityGraphAttributePaths() { return null; } + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("name", name) + .toString(); + } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java index 1236200..a91635f 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java @@ -1,26 +1,31 @@ package com.cosium.spring.data.jpa.entity.graph.repository.support; +import com.google.common.base.MoreObjects; +import org.springframework.core.ResolvableType; import org.springframework.data.jpa.repository.query.JpaEntityGraph; import org.springframework.util.Assert; /** * Wrapper class allowing to hold a {@link JpaEntityGraph} with its associated domain class. - * * Created on 23/11/16. * * @author Reda.Housni-Alaoui */ class EntityGraphBean { + private final JpaEntityGraph jpaEntityGraph; private final Class domainClass; + private final ResolvableType returnType; private final boolean optional; - public EntityGraphBean(JpaEntityGraph jpaEntityGraph, Class domainClass, boolean optional) { + public EntityGraphBean(JpaEntityGraph jpaEntityGraph, Class domainClass, ResolvableType returnType, boolean optional) { Assert.notNull(jpaEntityGraph); Assert.notNull(domainClass); + Assert.notNull(returnType); this.jpaEntityGraph = jpaEntityGraph; this.domainClass = domainClass; + this.returnType = returnType; this.optional = optional; } @@ -44,4 +49,29 @@ public Class getDomainClass() { public boolean isOptional() { return optional; } + + /** + * @return True if this EntityGraph seems valid + */ + public boolean isValid() { + if (domainClass.isAssignableFrom(returnType.resolve())) { + return true; + } + for (Class genericType : returnType.resolveGenerics()) { + if (domainClass.isAssignableFrom(genericType)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("jpaEntityGraph", jpaEntityGraph) + .add("domainClass", domainClass) + .add("returnType", returnType) + .add("optional", optional) + .toString(); + } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java index a2b36b3..43eb109 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java @@ -80,6 +80,7 @@ private boolean isQueryCreationEligible(EntityGraphBean entityGraphCandidate, Me return resultType == null || resultType.equals(entityGraphCandidate.getDomainClass()); } + /** * Push the current entity graph to the find method query hints. * diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 29f3ecf..9bfb64c 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -8,7 +8,9 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.ProxyFactory; +import org.springframework.aop.framework.ReflectiveMethodInvocation; import org.springframework.core.NamedThreadLocal; +import org.springframework.core.ResolvableType; import org.springframework.data.jpa.repository.query.JpaEntityGraph; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor; @@ -57,8 +59,8 @@ private static boolean isEmpty(EntityGraph entityGraph) { private static class JpaEntityGraphMethodInterceptor implements MethodInterceptor { private static final String DEFAULT_ENTITYGRAPH_NAME_SUFFIX = ".default"; - private final Class domainClass; - private final EntityGraphBean defaultEntityGraph; + private final Class domainClass; + private final EntityGraph defaultEntityGraph; JpaEntityGraphMethodInterceptor(EntityManager entityManager, Class domainClass) { this.domainClass = domainClass; @@ -69,18 +71,18 @@ private static class JpaEntityGraphMethodInterceptor implements MethodIntercepto * @param entityManager * @return The default entity graph if it exists. Null otherwise. */ - private EntityGraphBean findDefaultEntityGraph(EntityManager entityManager){ - EntityGraphBean entityGraphBean = null; - List> entityGraphs = entityManager.getEntityGraphs(domainClass); + private EntityGraph findDefaultEntityGraph(EntityManager entityManager) { + EntityGraph defaultEntityGraph = null; + List> entityGraphs = (List>) entityManager.getEntityGraphs(domainClass); for (javax.persistence.EntityGraph entityGraph : entityGraphs) { if (entityGraph.getName().endsWith(DEFAULT_ENTITYGRAPH_NAME_SUFFIX)) { - if(entityGraphBean != null){ - throw new RuntimeException("Multiple default entity graphs detected : " + entityGraph.getName() + " and " + entityGraphBean.getJpaEntityGraph().getName()); + if (defaultEntityGraph != null) { + throw new RuntimeException("Multiple default entity graphs detected : " + entityGraph.getName() + " and " + defaultEntityGraph.getEntityGraphName()); } - entityGraphBean = buildEntityGraphBean(EntityGraphUtils.fromName(entityGraph.getName()), true); + defaultEntityGraph = EntityGraphUtils.fromName(entityGraph.getName()); } } - return entityGraphBean; + return defaultEntityGraph; } @Override @@ -94,20 +96,35 @@ public Object invoke(MethodInvocation invocation) throws Throwable { entityGraph = (EntityGraph) argument; break; } - EntityGraphBean entityGraphBean = isEmpty(entityGraph)? defaultEntityGraph : buildEntityGraphBean(entityGraph, false); - if (entityGraphBean != null) { - CURRENT_ENTITY_GRAPH.set(entityGraphBean); + + boolean emptyEntityGraph = isEmpty(entityGraph); + + Class implementationClass; + if (invocation instanceof ReflectiveMethodInvocation) { + implementationClass = ((ReflectiveMethodInvocation) invocation).getProxy().getClass(); + } else { + implementationClass = invocation.getThis().getClass(); + } + + EntityGraphBean entityGraphCandidate = buildEntityGraphCandidate( + emptyEntityGraph ? defaultEntityGraph : entityGraph, + ResolvableType.forMethodReturnType(invocation.getMethod(), implementationClass), + emptyEntityGraph + ); + + if (entityGraphCandidate != null) { + CURRENT_ENTITY_GRAPH.set(entityGraphCandidate); } try { return invocation.proceed(); } finally { - if (entityGraphBean != null) { + if (entityGraphCandidate != null) { CURRENT_ENTITY_GRAPH.remove(); } } } - private EntityGraphBean buildEntityGraphBean(EntityGraph entityGraph, boolean optional) { + private EntityGraphBean buildEntityGraphCandidate(EntityGraph entityGraph, ResolvableType returnType, boolean optional) { Assert.notNull(entityGraph.getEntityGraphType()); org.springframework.data.jpa.repository.EntityGraph.EntityGraphType type; @@ -129,8 +146,7 @@ private EntityGraphBean buildEntityGraphBean(EntityGraph entityGraph, boolean op attributePaths != null ? attributePaths.toArray(new String[attributePaths.size()]) : null ); - return new EntityGraphBean(jpaEntityGraph, domainClass, optional); + return new EntityGraphBean(jpaEntityGraph, domainClass, returnType, optional); } - } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java index e431c8e..192027a 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java @@ -2,7 +2,6 @@ import javax.persistence.EntityManager; import javax.persistence.Query; - import java.util.Arrays; import java.util.List; import java.util.Map; @@ -28,14 +27,14 @@ class RepositoryQueryEntityGraphInjector implements MethodInterceptor { private final EntityManager entityManager; private final EntityGraphBean entityGraphCandidate; - private RepositoryQueryEntityGraphInjector(EntityManager entityManager, EntityGraphBean entityGraphCandidate){ + private RepositoryQueryEntityGraphInjector(EntityManager entityManager, EntityGraphBean entityGraphCandidate) { Assert.notNull(entityManager); Assert.notNull(entityGraphCandidate); this.entityManager = entityManager; this.entityGraphCandidate = entityGraphCandidate; } - static Query proxy(Query query, EntityManager entityManager, EntityGraphBean entityGraphCandidate){ + static Query proxy(Query query, EntityManager entityManager, EntityGraphBean entityGraphCandidate) { ProxyFactory proxyFactory = new ProxyFactory(query); proxyFactory.addAdvice(new RepositoryQueryEntityGraphInjector(entityManager, entityGraphCandidate)); return (Query) proxyFactory.getProxy(); @@ -43,22 +42,30 @@ static Query proxy(Query query, EntityManager entityManager, EntityGraphBean ent @Override public Object invoke(MethodInvocation invocation) throws Throwable { - if(EXECUTE_QUERY_METHODS.contains(invocation.getMethod().getName())){ + if (EXECUTE_QUERY_METHODS.contains(invocation.getMethod().getName())) { addEntityGraphToQuery((Query) invocation.getThis()); } return invocation.proceed(); } - private void addEntityGraphToQuery(Query query){ - if(entityGraphCandidate.isOptional() && QueryHintsUtils.containsEntityGraph(query.getHints())){ + private void addEntityGraphToQuery(Query query) { + if (entityGraphCandidate.isOptional() && QueryHintsUtils.containsEntityGraph(query.getHints())) { LOG.trace("The query hints passed with the find method already hold an entity graph. Overriding aborted because the candidate EntityGraph is optional."); return; } + if (!entityGraphCandidate.isValid()) { + if (entityGraphCandidate.isOptional()) { + LOG.trace("Cannot apply EntityGraph {}", entityGraphCandidate); + return; + } else { + throw new RuntimeException("Cannot apply EntityGraph " + entityGraphCandidate); + } + } + QueryHintsUtils.removeEntityGraphs(query.getHints()); Map hints = QueryHintsUtils.buildQueryHints(entityManager, entityGraphCandidate); for (Map.Entry hint : hints.entrySet()) { query.setHint(hint.getKey(), hint.getValue()); } } - } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index b218ac2..157fbe3 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -117,4 +117,10 @@ public void given_products_when_countproductsbyname_then_it_should_work(){ productRepository.countByName("Product 1"); } + @Transactional + @Test + public void given_products_when_findAllRaw_then_it_should_work(){ + productRepository.findAllRaw(); + } + } \ No newline at end of file diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java index 06ef407..08b648e 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java @@ -6,6 +6,7 @@ import com.cosium.spring.data.jpa.entity.graph.repository.JpaEntityGraphQueryDslPredicateExecutor; import com.cosium.spring.data.jpa.entity.graph.repository.JpaEntityGraphRepository; import com.cosium.spring.data.jpa.entity.graph.repository.JpaEntityGraphSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; /** * Created on 22/11/16. @@ -23,4 +24,7 @@ public interface ProductRepository Product findByBarcode(String barcode); long countByName(String name); + + @Query("select p.name from Product p") + List findAllRaw(); } From 1f995918224f70ae45763ea8e6a6cb6ffa26a106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 23:10:59 +0100 Subject: [PATCH 37/81] Add release script --- release.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 release.sh diff --git a/release.sh b/release.sh new file mode 100644 index 0000000..03c6696 --- /dev/null +++ b/release.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +mvn --batch-mode clean release:prepare release:perform && git push && git push --tags \ No newline at end of file From 8a1cf01a8ce6718ad26aeb887f619e16f1668a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 23:11:52 +0100 Subject: [PATCH 38/81] Add release script --- release.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 release.sh diff --git a/release.sh b/release.sh old mode 100644 new mode 100755 From e456b6482b3ae5d1e532de440528b27d8f813c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 23:13:25 +0100 Subject: [PATCH 39/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.06 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c08e764..9b895d6 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.06-SNAPSHOT + 1.10.06 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.06 From 3355d0faa3bcd7cbe53732f29a0b81fc06aa44e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 23:13:25 +0100 Subject: [PATCH 40/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9b895d6..f2f1132 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.06 + 1.10.07-SNAPSHOT 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.06 + HEAD From 2242bc0fce9fef468098e083f80cfb6226b25249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 23:14:39 +0100 Subject: [PATCH 41/81] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a0c173f..26500f3 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.05 + 1.10.06 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From ad438aad82a7954d099a1a492647ab38ef4b6537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 23:19:50 +0100 Subject: [PATCH 42/81] NPE when there is no default EntityGraph (cherry picked from commit 5fe885c) --- .../RepositoryMethodEntityGraphExtractor.java | 4 ++++ .../repository/JpaEntityGraphRepositoryTest.java | 9 +++++++++ .../graph/repository/sample/BrandRepository.java | 12 ++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/BrandRepository.java diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 9bfb64c..53041da 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -125,6 +125,10 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } private EntityGraphBean buildEntityGraphCandidate(EntityGraph entityGraph, ResolvableType returnType, boolean optional) { + if(entityGraph == null){ + return null; + } + Assert.notNull(entityGraph.getEntityGraphType()); org.springframework.data.jpa.repository.EntityGraph.EntityGraphType type; diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index 157fbe3..897757b 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -12,6 +12,7 @@ import com.cosium.spring.data.jpa.entity.graph.BaseTest; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; +import com.cosium.spring.data.jpa.entity.graph.repository.sample.BrandRepository; import com.cosium.spring.data.jpa.entity.graph.repository.sample.EntityGraphSpecification; import com.cosium.spring.data.jpa.entity.graph.repository.sample.Product; import com.cosium.spring.data.jpa.entity.graph.repository.sample.ProductRepository; @@ -34,6 +35,8 @@ public class JpaEntityGraphRepositoryTest extends BaseTest { @Inject private ProductRepository productRepository; + @Inject + private BrandRepository brandRepository; @Transactional @Test @@ -123,4 +126,10 @@ public void given_products_when_findAllRaw_then_it_should_work(){ productRepository.findAllRaw(); } + @Transactional + @Test + public void given_entity_without_default_eg_when_findall_then_it_should_work(){ + brandRepository.findAll(); + } + } \ No newline at end of file diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/BrandRepository.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/BrandRepository.java new file mode 100644 index 0000000..c785f0a --- /dev/null +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/BrandRepository.java @@ -0,0 +1,12 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.sample; + +import com.cosium.spring.data.jpa.entity.graph.repository.JpaEntityGraphRepository; + +/** + * Created on 24/11/16. + * + * @author Reda.Housni-Alaoui + */ +public interface BrandRepository extends JpaEntityGraphRepository { + +} From 145f3acc8cba935043affe242a9b15680cb69022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 23:20:54 +0100 Subject: [PATCH 43/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.07 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f2f1132..5d60ce2 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.07-SNAPSHOT + 1.10.07 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.07 From c15a651358aa79c4bdb724149625fe74a60a5e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 23:20:54 +0100 Subject: [PATCH 44/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5d60ce2..28b2da3 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.07 + 1.10.08-SNAPSHOT 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.07 + HEAD From 79a5c8a35dfd28ffedc670ed89858c91db188913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 24 Nov 2016 23:21:51 +0100 Subject: [PATCH 45/81] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 26500f3..8b78cac 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.06 + 1.10.07 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From b705596c87c7e3ca198bd3ca43b1a590622bea8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Fri, 25 Nov 2016 09:35:41 +0100 Subject: [PATCH 46/81] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8b78cac..81c43a0 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ You can also pass a dynamically built EntityGraph by using DynamicEntityGraph im ### Default EntityGraph For an Entity, you can define its default EntityGraph. -And Entity default EntityGraph will be used each time the Entity repository method is called without EntityGraph. +An Entity default EntityGraph will be used each time the Entity repository method is called without EntityGraph. A default EntityGraph name must end with `.default`. @@ -110,4 +110,4 @@ public class Product { ```java // This call will make use of "Product.default" EntityGraph. productRepository.findOne(1L); -``` \ No newline at end of file +``` From 216a1119850ad388fe2102a4b76ef0a81ff494db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Fri, 25 Nov 2016 09:49:20 +0100 Subject: [PATCH 47/81] Enhance README (cherry picked from commit 45d69d9) --- README.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 81c43a0..8a8f001 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,16 @@ -### Why? +# Spring Data JPA EntityGraph -Today, Spring Data JPA supports EntityGraph exlusively through annotations. +Today, [Spring Data JPA](https://github.com/spring-projects/spring-data-jpa) supports EntityGraph exlusively through annotations. Thus, for a method, the choice of EntityGraph must be made before compilation. -This library gives the ability to pass EntityGraph on any Spring Data JPA repository method as an argument, making the EntityGraph choice fully dynamic. +This extension gives the ability to pass EntityGraph on any Spring Data JPA repository method as an argument, making the EntityGraph choice fully dynamic. -### Spring Data JPA Compatibility +Example: +```java +productRepository.findByName("foo", EntityGraphUtils.fromName("Product.brand")); +``` + +## Compatibility This library follows the Spring Data JPA versionning semantic. @@ -14,7 +19,7 @@ spring-data-jpa-entity-graph | spring-data-jpa 1.11.x | 1.11.y 1.10.x | 1.10.y -### Quick start +## Quick start 1. In addition to spring-data-jpa, add the library dependency : @@ -36,7 +41,7 @@ spring-data-jpa-entity-graph | spring-data-jpa ``` 3. Make sure your repositories extend `JpaEntityGraphRepository`, `JpaEntityGraphSpecificationExecutor` and/or `JpaEntityGraphQueryDslPredicateExecutor` -### Basic Usage +## Basic Usage Let's consider the following entities and repository : ```java @@ -84,7 +89,7 @@ Or any method you like. You can also pass a dynamically built EntityGraph by using DynamicEntityGraph implementation. -### Default EntityGraph +## Default EntityGraph For an Entity, you can define its default EntityGraph. An Entity default EntityGraph will be used each time the Entity repository method is called without EntityGraph. From a738d5838695a07c6553262ab275ca43e8459835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Fri, 25 Nov 2016 09:53:22 +0100 Subject: [PATCH 48/81] Enhance README (cherry picked from commit 4b260fb) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a8f001..0faa5d4 100644 --- a/README.md +++ b/README.md @@ -77,17 +77,19 @@ public interface ProductRepository extends JpaEntityGraphRepository Date: Sun, 27 Nov 2016 11:14:08 +0100 Subject: [PATCH 49/81] Type exceptions (cherry picked from commit 7880c02) --- .../InapplicableEntityGraphException.java | 13 +++++++++++++ .../MultipleDefaultEntityGraphException.java | 14 ++++++++++++++ .../exception/RepositoryEntityGraphException.java | 14 ++++++++++++++ .../RepositoryMethodEntityGraphExtractor.java | 5 +++-- .../RepositoryQueryEntityGraphInjector.java | 3 ++- 5 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/InapplicableEntityGraphException.java create mode 100644 src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/MultipleDefaultEntityGraphException.java create mode 100644 src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/RepositoryEntityGraphException.java diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/InapplicableEntityGraphException.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/InapplicableEntityGraphException.java new file mode 100644 index 0000000..315601f --- /dev/null +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/InapplicableEntityGraphException.java @@ -0,0 +1,13 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.exception; + +/** + * Created on 27/11/16. + * + * @author Reda.Housni-Alaoui + */ +public class InapplicableEntityGraphException extends RepositoryEntityGraphException { + + public InapplicableEntityGraphException(String message) { + super(message); + } +} diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/MultipleDefaultEntityGraphException.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/MultipleDefaultEntityGraphException.java new file mode 100644 index 0000000..b426f3c --- /dev/null +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/MultipleDefaultEntityGraphException.java @@ -0,0 +1,14 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.exception; + + +/** + * Created on 27/11/16. + * + * @author Reda.Housni-Alaoui + */ +public class MultipleDefaultEntityGraphException extends RepositoryEntityGraphException { + + public MultipleDefaultEntityGraphException(String entityGraph1Name, String entityGraph2Name) { + super("Multiple default entity graphs detected : " + entityGraph1Name + " and " + entityGraph2Name); + } +} diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/RepositoryEntityGraphException.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/RepositoryEntityGraphException.java new file mode 100644 index 0000000..39cea7a --- /dev/null +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/RepositoryEntityGraphException.java @@ -0,0 +1,14 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.exception; + +/** + * Created on 27/11/16. + * + * @author Reda.Housni-Alaoui + */ +public abstract class RepositoryEntityGraphException extends RuntimeException { + + public RepositoryEntityGraphException(String message) { + super(message); + } + +} diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 53041da..4223141 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -5,6 +5,7 @@ import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; +import com.cosium.spring.data.jpa.entity.graph.repository.exception.MultipleDefaultEntityGraphException; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.ProxyFactory; @@ -77,7 +78,7 @@ private EntityGraph findDefaultEntityGraph(EntityManager entityManager) { for (javax.persistence.EntityGraph entityGraph : entityGraphs) { if (entityGraph.getName().endsWith(DEFAULT_ENTITYGRAPH_NAME_SUFFIX)) { if (defaultEntityGraph != null) { - throw new RuntimeException("Multiple default entity graphs detected : " + entityGraph.getName() + " and " + defaultEntityGraph.getEntityGraphName()); + throw new MultipleDefaultEntityGraphException(entityGraph.getName(), defaultEntityGraph.getEntityGraphName()); } defaultEntityGraph = EntityGraphUtils.fromName(entityGraph.getName()); } @@ -140,7 +141,7 @@ private EntityGraphBean buildEntityGraphCandidate(EntityGraph entityGraph, Resol type = org.springframework.data.jpa.repository.EntityGraph.EntityGraphType.LOAD; break; default: - throw new RuntimeException("Unknown entity graph type"); + throw new RuntimeException("Unexpected entity graph type '" + entityGraph.getEntityGraphType() + "'"); } List attributePaths = entityGraph.getEntityGraphAttributePaths(); diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java index 192027a..5334fa9 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; +import com.cosium.spring.data.jpa.entity.graph.repository.exception.InapplicableEntityGraphException; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; @@ -58,7 +59,7 @@ private void addEntityGraphToQuery(Query query) { LOG.trace("Cannot apply EntityGraph {}", entityGraphCandidate); return; } else { - throw new RuntimeException("Cannot apply EntityGraph " + entityGraphCandidate); + throw new InapplicableEntityGraphException("Cannot apply EntityGraph " + entityGraphCandidate + " to the the current query"); } } From 9192f365fb1f58eb9d0ee72b56a8fdd03898180a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Sun, 27 Nov 2016 11:50:45 +0100 Subject: [PATCH 50/81] Throw InapplicableEntityGraphException in case of mandatory EntityGraph on projection usage (cherry picked from commit 036351f) --- .../repository/support/EntityGraphBean.java | 34 +++++++++++-------- .../RepositoryMethodEntityGraphExtractor.java | 14 ++++++++ .../RepositoryQueryEntityGraphInjector.java | 8 ----- .../JpaEntityGraphRepositoryTest.java | 28 ++++++++++----- .../graph/repository/sample/ProductName.java | 10 ++++++ .../repository/sample/ProductRepository.java | 2 ++ 6 files changed, 66 insertions(+), 30 deletions(-) create mode 100644 src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductName.java diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java index a91635f..897f34d 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java @@ -15,18 +15,32 @@ class EntityGraphBean { private final JpaEntityGraph jpaEntityGraph; private final Class domainClass; - private final ResolvableType returnType; + private final ResolvableType repositoryMethodReturnType; private final boolean optional; + private final boolean valid; - public EntityGraphBean(JpaEntityGraph jpaEntityGraph, Class domainClass, ResolvableType returnType, boolean optional) { + public EntityGraphBean(JpaEntityGraph jpaEntityGraph, Class domainClass, ResolvableType repositoryMethodReturnType, boolean optional) { Assert.notNull(jpaEntityGraph); Assert.notNull(domainClass); - Assert.notNull(returnType); + Assert.notNull(repositoryMethodReturnType); this.jpaEntityGraph = jpaEntityGraph; this.domainClass = domainClass; - this.returnType = returnType; + this.repositoryMethodReturnType = repositoryMethodReturnType; this.optional = optional; + this.valid = computeValidity(); + } + + private boolean computeValidity(){ + if (domainClass.isAssignableFrom(repositoryMethodReturnType.resolve())) { + return true; + } + for (Class genericType : repositoryMethodReturnType.resolveGenerics()) { + if (domainClass.isAssignableFrom(genericType)) { + return true; + } + } + return false; } /** @@ -54,15 +68,7 @@ public boolean isOptional() { * @return True if this EntityGraph seems valid */ public boolean isValid() { - if (domainClass.isAssignableFrom(returnType.resolve())) { - return true; - } - for (Class genericType : returnType.resolveGenerics()) { - if (domainClass.isAssignableFrom(genericType)) { - return true; - } - } - return false; + return valid; } @Override @@ -70,7 +76,7 @@ public String toString() { return MoreObjects.toStringHelper(this) .add("jpaEntityGraph", jpaEntityGraph) .add("domainClass", domainClass) - .add("returnType", returnType) + .add("repositoryMethodReturnType", repositoryMethodReturnType) .add("optional", optional) .toString(); } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 4223141..f89e445 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -5,9 +5,12 @@ import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; +import com.cosium.spring.data.jpa.entity.graph.repository.exception.InapplicableEntityGraphException; import com.cosium.spring.data.jpa.entity.graph.repository.exception.MultipleDefaultEntityGraphException; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.framework.ReflectiveMethodInvocation; import org.springframework.core.NamedThreadLocal; @@ -26,6 +29,8 @@ */ class RepositoryMethodEntityGraphExtractor implements RepositoryProxyPostProcessor { + private static final Logger LOG = LoggerFactory.getLogger(RepositoryMethodEntityGraphExtractor.class); + private static final ThreadLocal CURRENT_ENTITY_GRAPH = new NamedThreadLocal("Thread local holding the current spring data jpa repository entity graph"); @@ -113,6 +118,15 @@ public Object invoke(MethodInvocation invocation) throws Throwable { emptyEntityGraph ); + if (entityGraphCandidate != null && !entityGraphCandidate.isValid()) { + if (entityGraphCandidate.isOptional()) { + LOG.trace("Cannot apply EntityGraph {}", entityGraphCandidate); + entityGraphCandidate = null; + } else { + throw new InapplicableEntityGraphException("Cannot apply EntityGraph " + entityGraphCandidate + " to the the current query"); + } + } + if (entityGraphCandidate != null) { CURRENT_ENTITY_GRAPH.set(entityGraphCandidate); } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java index 5334fa9..17fe161 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java @@ -54,14 +54,6 @@ private void addEntityGraphToQuery(Query query) { LOG.trace("The query hints passed with the find method already hold an entity graph. Overriding aborted because the candidate EntityGraph is optional."); return; } - if (!entityGraphCandidate.isValid()) { - if (entityGraphCandidate.isOptional()) { - LOG.trace("Cannot apply EntityGraph {}", entityGraphCandidate); - return; - } else { - throw new InapplicableEntityGraphException("Cannot apply EntityGraph " + entityGraphCandidate + " to the the current query"); - } - } QueryHintsUtils.removeEntityGraphs(query.getHints()); Map hints = QueryHintsUtils.buildQueryHints(entityManager, entityGraphCandidate); diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index 897757b..6f6332f 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -1,8 +1,10 @@ package com.cosium.spring.data.jpa.entity.graph.repository; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.*; import javax.inject.Inject; +import javax.persistence.Entity; +import javax.persistence.EntityManager; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; @@ -12,10 +14,8 @@ import com.cosium.spring.data.jpa.entity.graph.BaseTest; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; -import com.cosium.spring.data.jpa.entity.graph.repository.sample.BrandRepository; -import com.cosium.spring.data.jpa.entity.graph.repository.sample.EntityGraphSpecification; -import com.cosium.spring.data.jpa.entity.graph.repository.sample.Product; -import com.cosium.spring.data.jpa.entity.graph.repository.sample.ProductRepository; +import com.cosium.spring.data.jpa.entity.graph.repository.exception.InapplicableEntityGraphException; +import com.cosium.spring.data.jpa.entity.graph.repository.sample.*; import com.github.springtestdbunit.annotation.DatabaseSetup; import com.github.springtestdbunit.annotation.DatabaseTearDown; import org.hibernate.Hibernate; @@ -117,19 +117,31 @@ public void given_default_eg_when_findByBarcode_with_eg_annotation_on_brand_eg_t @Transactional @Test public void given_products_when_countproductsbyname_then_it_should_work(){ - productRepository.countByName("Product 1"); + assertThat(productRepository.countByName("Product 1")).isEqualTo(1); } @Transactional @Test public void given_products_when_findAllRaw_then_it_should_work(){ - productRepository.findAllRaw(); + assertThat(productRepository.findAllRaw()).isNotEmpty(); } @Transactional @Test public void given_entity_without_default_eg_when_findall_then_it_should_work(){ - brandRepository.findAll(); + assertThat(brandRepository.findAll()).isNotEmpty(); } + @Transactional + @Test(expected = InapplicableEntityGraphException.class) + public void given_products_and_ProductName_projection_when_findProductNameByName_with_eg_then_it_should_fail(){ + productRepository.findProductNameByName("Product 1", EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + } + + @Transactional + @Test + public void given_products_and_ProductName_projection_when_findProductNameByName_without_eg_then_it_should_work(){ + ProductName productName = productRepository.findProductNameByName("Product 1", EntityGraphUtils.empty()); + assertThat(productName).isNotNull(); + } } \ No newline at end of file diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductName.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductName.java new file mode 100644 index 0000000..d6b88e1 --- /dev/null +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductName.java @@ -0,0 +1,10 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.sample; + +/** + * Created on 27/11/16. + * + * @author Reda.Housni-Alaoui + */ +public interface ProductName { + String getName(); +} diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java index 08b648e..1136dcc 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java @@ -20,6 +20,8 @@ public interface ProductRepository List findByName(String name, EntityGraph entityGraph); + ProductName findProductNameByName(String name, EntityGraph entityGraph); + @org.springframework.data.jpa.repository.EntityGraph(value = Product.PRODUCT_BRAND_EG) Product findByBarcode(String barcode); From bd359af421a1f2562101461768c63f626f0150b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Sun, 27 Nov 2016 12:19:05 +0100 Subject: [PATCH 51/81] Fail when multiple EntityGraphs are detected on one repository method invocation (cherry picked from commit 816e47d) --- .../MultipleEntityGraphException.java | 13 ++++++ .../RepositoryMethodEntityGraphExtractor.java | 17 ++++--- .../JpaEntityGraphRepositoryTest.java | 45 +++++++++++++++++++ .../sample/EmptyEntityGraphSpecification.java | 37 +++++++++++++++ .../repository/sample/ProductRepository.java | 2 + 5 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/MultipleEntityGraphException.java create mode 100644 src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EmptyEntityGraphSpecification.java diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/MultipleEntityGraphException.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/MultipleEntityGraphException.java new file mode 100644 index 0000000..61d3bb6 --- /dev/null +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/exception/MultipleEntityGraphException.java @@ -0,0 +1,13 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.exception; + +/** + * Created on 27/11/16. + * + * @author Reda.Housni-Alaoui + */ +public class MultipleEntityGraphException extends RuntimeException { + + public MultipleEntityGraphException(String message) { + super(message); + } +} diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index f89e445..0d3c585 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -7,6 +7,7 @@ import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; import com.cosium.spring.data.jpa.entity.graph.repository.exception.InapplicableEntityGraphException; import com.cosium.spring.data.jpa.entity.graph.repository.exception.MultipleDefaultEntityGraphException; +import com.cosium.spring.data.jpa.entity.graph.repository.exception.MultipleEntityGraphException; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; @@ -94,16 +95,20 @@ private EntityGraph findDefaultEntityGraph(EntityManager entityManager) { @Override public Object invoke(MethodInvocation invocation) throws Throwable { Object[] arguments = invocation.getArguments(); - EntityGraph entityGraph = null; + EntityGraph providedEntityGraph = null; for (Object argument : arguments) { if (!(argument instanceof EntityGraph)) { continue; } - entityGraph = (EntityGraph) argument; - break; + EntityGraph newEntityGraph = (EntityGraph) argument; + if (providedEntityGraph != null) { + throw new MultipleEntityGraphException("Duplicate EntityGraphs detected. '" + + providedEntityGraph + "' and '" + newEntityGraph + "' were passed to method " + invocation.getMethod()); + } + providedEntityGraph = newEntityGraph; } - boolean emptyEntityGraph = isEmpty(entityGraph); + boolean emptyEntityGraph = isEmpty(providedEntityGraph); Class implementationClass; if (invocation instanceof ReflectiveMethodInvocation) { @@ -113,7 +118,7 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } EntityGraphBean entityGraphCandidate = buildEntityGraphCandidate( - emptyEntityGraph ? defaultEntityGraph : entityGraph, + emptyEntityGraph ? defaultEntityGraph : providedEntityGraph, ResolvableType.forMethodReturnType(invocation.getMethod(), implementationClass), emptyEntityGraph ); @@ -140,7 +145,7 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } private EntityGraphBean buildEntityGraphCandidate(EntityGraph entityGraph, ResolvableType returnType, boolean optional) { - if(entityGraph == null){ + if (entityGraph == null) { return null; } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index 6f6332f..1d56403 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -15,6 +15,7 @@ import com.cosium.spring.data.jpa.entity.graph.BaseTest; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; import com.cosium.spring.data.jpa.entity.graph.repository.exception.InapplicableEntityGraphException; +import com.cosium.spring.data.jpa.entity.graph.repository.exception.MultipleEntityGraphException; import com.cosium.spring.data.jpa.entity.graph.repository.sample.*; import com.github.springtestdbunit.annotation.DatabaseSetup; import com.github.springtestdbunit.annotation.DatabaseTearDown; @@ -144,4 +145,48 @@ public void given_products_and_ProductName_projection_when_findProductNameByName ProductName productName = productRepository.findProductNameByName("Product 1", EntityGraphUtils.empty()); assertThat(productName).isNotNull(); } + + @Transactional + @Test(expected = MultipleEntityGraphException.class) + public void given_products_when_findAllBySpec_with_two_non_empty_egs_then_it_should_fail(){ + productRepository.findAll(new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return null; + } + }, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + } + + @Transactional + @Test(expected = MultipleEntityGraphException.class) + public void given_products_when_findAllBySpec_with_an_empty_eg_and_a_non_empty_one_then_it_should_fail(){ + productRepository.findAll(new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return null; + } + }, EntityGraphUtils.empty()); + } + + @Transactional + @Test(expected = MultipleEntityGraphException.class) + public void given_products_when_findAllBySpec_with_two_empty_eg_then_it_should_fail(){ + productRepository.findAll(new EmptyEntityGraphSpecification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return null; + } + }, EntityGraphUtils.empty()); + } + + @Transactional + @Test(expected = MultipleEntityGraphException.class) + public void given_products_when_findAllBySpec_with_a_non_empty_eg_and_an_empty_one_then_it_should_fail(){ + productRepository.findAll(new EmptyEntityGraphSpecification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return null; + } + }, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + } } \ No newline at end of file diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EmptyEntityGraphSpecification.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EmptyEntityGraphSpecification.java new file mode 100644 index 0000000..54dbc07 --- /dev/null +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EmptyEntityGraphSpecification.java @@ -0,0 +1,37 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.sample; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import java.util.List; + +import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; +import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphType; +import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; +import org.springframework.data.jpa.domain.Specification; + +/** + * Created on 27/11/16. + * + * @author Reda.Housni-Alaoui + */ +public abstract class EmptyEntityGraphSpecification implements Specification, EntityGraph { + + private final EntityGraph entityGraph = EntityGraphUtils.empty(); + + @Override + public EntityGraphType getEntityGraphType() { + return entityGraph.getEntityGraphType(); + } + + @Override + public String getEntityGraphName() { + return entityGraph.getEntityGraphName(); + } + + @Override + public List getEntityGraphAttributePaths() { + return entityGraph.getEntityGraphAttributePaths(); + } +} diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java index 1136dcc..69387a6 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java @@ -29,4 +29,6 @@ public interface ProductRepository @Query("select p.name from Product p") List findAllRaw(); + + } From a7b23ae189c8d0bde82516ddbe3d1eaa8f66624d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Sun, 27 Nov 2016 12:22:17 +0100 Subject: [PATCH 52/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.08 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 28b2da3..8efcfd0 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.08-SNAPSHOT + 1.10.08 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.08 From ed4cf9d1a1878e79524f9f1b8170c5cca238c78d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Sun, 27 Nov 2016 12:22:17 +0100 Subject: [PATCH 53/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8efcfd0..b2d80e5 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.08 + 1.10.09-SNAPSHOT 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.08 + HEAD From fb87d0c9276b5eca4de762cb9f9f7dbcf4092b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Sun, 27 Nov 2016 12:25:14 +0100 Subject: [PATCH 54/81] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0faa5d4..11c478f 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.07 + 1.10.08 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From df1eba992da0eb829632f90cc8cd4d15cacebd9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 09:58:26 +0100 Subject: [PATCH 55/81] Don't fail on method returning void (cherry picked from commit d4fa4ce) --- .../repository/support/EntityGraphBean.java | 5 +-- .../JpaEntityGraphCustomRepositoryTest.java | 32 +++++++++++++++++++ .../repository/sample/ProductRepository.java | 5 ++- .../sample/ProductRepositoryCustom.java | 14 ++++++++ .../sample/ProductRepositoryImpl.java | 19 +++++++++++ 5 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphCustomRepositoryTest.java create mode 100644 src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryCustom.java create mode 100644 src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryImpl.java diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java index 897f34d..240aefe 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java @@ -31,8 +31,9 @@ public EntityGraphBean(JpaEntityGraph jpaEntityGraph, Class domainClass, Reso this.valid = computeValidity(); } - private boolean computeValidity(){ - if (domainClass.isAssignableFrom(repositoryMethodReturnType.resolve())) { + private boolean computeValidity() { + Class resolvedReturnType = repositoryMethodReturnType.resolve(); + if (Void.TYPE.equals(resolvedReturnType) || domainClass.isAssignableFrom(resolvedReturnType)) { return true; } for (Class genericType : repositoryMethodReturnType.resolveGenerics()) { diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphCustomRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphCustomRepositoryTest.java new file mode 100644 index 0000000..df47cf8 --- /dev/null +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphCustomRepositoryTest.java @@ -0,0 +1,32 @@ +package com.cosium.spring.data.jpa.entity.graph.repository; + +import javax.inject.Inject; + +import com.cosium.spring.data.jpa.entity.graph.BaseTest; +import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; +import com.cosium.spring.data.jpa.entity.graph.repository.sample.Product; +import com.cosium.spring.data.jpa.entity.graph.repository.sample.ProductRepository; +import com.github.springtestdbunit.annotation.DatabaseSetup; +import com.github.springtestdbunit.annotation.DatabaseTearDown; +import org.junit.Test; +import org.springframework.transaction.annotation.Transactional; + +/** + * Created on 28/11/16. + * + * @author Reda.Housni-Alaoui + */ +@DatabaseSetup(BaseTest.DATASET) +@DatabaseTearDown +public class JpaEntityGraphCustomRepositoryTest extends BaseTest { + + @Inject + private ProductRepository productRepository; + + @Test + @Transactional + public void given_products_when_calling_customvoidmethod_with_eg_then_it_should_work(){ + productRepository.customMethod(EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + } + +} diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java index 69387a6..63590c1 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java @@ -16,7 +16,8 @@ public interface ProductRepository extends JpaEntityGraphRepository, JpaEntityGraphSpecificationExecutor, - JpaEntityGraphQueryDslPredicateExecutor { + JpaEntityGraphQueryDslPredicateExecutor, + ProductRepositoryCustom { List findByName(String name, EntityGraph entityGraph); @@ -29,6 +30,4 @@ public interface ProductRepository @Query("select p.name from Product p") List findAllRaw(); - - } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryCustom.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryCustom.java new file mode 100644 index 0000000..480a1fe --- /dev/null +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryCustom.java @@ -0,0 +1,14 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.sample; + +import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; + +/** + * Created on 28/11/16. + * + * @author Reda.Housni-Alaoui + */ +public interface ProductRepositoryCustom { + + void customMethod(EntityGraph entityGraph); + +} diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryImpl.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryImpl.java new file mode 100644 index 0000000..06248bf --- /dev/null +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryImpl.java @@ -0,0 +1,19 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.sample; + +import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; +import org.springframework.stereotype.Component; + +/** + * Created on 28/11/16. + * + * @author Reda.Housni-Alaoui + */ +@Component +public class ProductRepositoryImpl implements ProductRepositoryCustom { + + @Override + public void customMethod(EntityGraph entityGraph) { + + } + +} From 8261bd5a87a883f3b1dfd8d5c8fe1f85e83cc04a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 09:59:50 +0100 Subject: [PATCH 56/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.09 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b2d80e5..f6ebb75 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.09-SNAPSHOT + 1.10.09 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.09 From 41b446b7061ec6e44748a7fdf5a1ead8122fb100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 09:59:50 +0100 Subject: [PATCH 57/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f6ebb75..b954e93 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.09 + 1.10.10-SNAPSHOT 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.09 + HEAD From 4c05da6d6b8f45597dda2b1746b61987860f0a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 10:02:35 +0100 Subject: [PATCH 58/81] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 11c478f..2633cec 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.08 + 1.10.09 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From 8facae482260ac882ffb60db7cc5ebd0e5474a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 10:32:13 +0100 Subject: [PATCH 59/81] Add the concept of optional EntityGraph (cherry picked from commit 844e919) --- .../graph/domain/AbstractEntityGraph.java | 24 ++++++++++++++++++- .../jpa/entity/graph/domain/EntityGraph.java | 6 +++++ .../entity/graph/domain/EntityGraphUtils.java | 19 ++++++++++++++- .../entity/graph/domain/NamedEntityGraph.java | 11 +++++---- .../RepositoryMethodEntityGraphExtractor.java | 2 +- .../JpaEntityGraphRepositoryTest.java | 8 ++++++- .../sample/EmptyEntityGraphSpecification.java | 9 +++---- .../sample/EntityGraphSpecification.java | 5 ++++ 8 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java index e9b1f2d..80c07a2 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/AbstractEntityGraph.java @@ -10,13 +10,20 @@ */ public abstract class AbstractEntityGraph implements EntityGraph{ - private EntityGraphType entityGraphType = EntityGraphType.FETCH; + protected static final EntityGraphType DEFAULT_ENTITY_GRAPH_TYPE = EntityGraphType.FETCH; + private EntityGraphType entityGraphType = DEFAULT_ENTITY_GRAPH_TYPE; + private boolean optional; public AbstractEntityGraph(){} public AbstractEntityGraph(EntityGraphType entityGraphType){ + this(entityGraphType, false); + } + + public AbstractEntityGraph(EntityGraphType entityGraphType, boolean optional){ Assert.notNull(entityGraphType); this.entityGraphType = entityGraphType; + this.optional = optional; } @Override @@ -29,11 +36,26 @@ public void setEntityGraphType(EntityGraphType entityGraphType) { this.entityGraphType = entityGraphType; } + /** + * False by default + * @return True if the EntityGraph is optional.
+ * Passing an optional EntityGraph to an unsupported method will not trigger {@link com.cosium.spring.data.jpa.entity.graph.repository.exception.InapplicableEntityGraphException}. + */ + @Override + public boolean isOptional() { + return optional; + } + + public void setOptional(boolean optional) { + this.optional = optional; + } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("entityGraphType", entityGraphType) + .add("optional", optional) .toString(); } + } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java index 420c99c..3931c3a 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraph.java @@ -23,4 +23,10 @@ public interface EntityGraph { * @return The attribute paths. May be null. */ List getEntityGraphAttributePaths(); + + /** + * @return True if the EntityGraph is optional.
+ * Passing an optional EntityGraph to an unsupported method will not trigger {@link com.cosium.spring.data.jpa.entity.graph.repository.exception.InapplicableEntityGraphException}. + */ + boolean isOptional(); } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java index bda603c..c49bbba 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/EntityGraphUtils.java @@ -20,12 +20,24 @@ public static EntityGraph empty() { /** * @param name The name of the targeted EntityGraph - * @return A EntityGraph referenced by name + * @return An EntityGraph referenced by name */ public static EntityGraph fromName(String name) { return new NamedEntityGraph(name); } + /** + * + * @param name The name of the targeted EntityGraph + * @param optional Is the EntityGraph usage optional? + * @return An EntityGraph referenced by name + */ + public static EntityGraph fromName(String name, boolean optional){ + NamedEntityGraph namedEntityGraph = new NamedEntityGraph(name); + namedEntityGraph.setOptional(optional); + return namedEntityGraph; + } + private static final class EmptyEntityGraph implements EntityGraph { @Override @@ -42,5 +54,10 @@ public String getEntityGraphName() { public List getEntityGraphAttributePaths() { return null; } + + @Override + public boolean isOptional() { + return false; + } } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java index 4a5d820..7b42357 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/domain/NamedEntityGraph.java @@ -14,15 +14,18 @@ public class NamedEntityGraph extends AbstractEntityGraph { private final String name; - public NamedEntityGraph(EntityGraphType type, String name) { - super(type); + public NamedEntityGraph(EntityGraphType type, boolean optional, String name) { + super(type, optional); Assert.hasLength(name); this.name = name; } + public NamedEntityGraph(EntityGraphType type, String name) { + this(type, false, name); + } + public NamedEntityGraph(String name){ - Assert.hasLength(name); - this.name = name; + this(DEFAULT_ENTITY_GRAPH_TYPE, name); } @Override diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 0d3c585..5c1cb5b 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -120,7 +120,7 @@ public Object invoke(MethodInvocation invocation) throws Throwable { EntityGraphBean entityGraphCandidate = buildEntityGraphCandidate( emptyEntityGraph ? defaultEntityGraph : providedEntityGraph, ResolvableType.forMethodReturnType(invocation.getMethod(), implementationClass), - emptyEntityGraph + emptyEntityGraph || providedEntityGraph.isOptional() ); if (entityGraphCandidate != null && !entityGraphCandidate.isValid()) { diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index 1d56403..6112d5c 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -135,10 +135,16 @@ public void given_entity_without_default_eg_when_findall_then_it_should_work(){ @Transactional @Test(expected = InapplicableEntityGraphException.class) - public void given_products_and_ProductName_projection_when_findProductNameByName_with_eg_then_it_should_fail(){ + public void given_products_and_ProductName_projection_when_findProductNameByName_with_mandatory_eg_then_it_should_fail(){ productRepository.findProductNameByName("Product 1", EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); } + @Transactional + @Test + public void given_products_and_ProductName_projection_when_findProductNameByName_with_optional_eg_then_it_should_not_fail(){ + productRepository.findProductNameByName("Product 1", EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG, true)); + } + @Transactional @Test public void given_products_and_ProductName_projection_when_findProductNameByName_without_eg_then_it_should_work(){ diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EmptyEntityGraphSpecification.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EmptyEntityGraphSpecification.java index 54dbc07..f0bb1cd 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EmptyEntityGraphSpecification.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EmptyEntityGraphSpecification.java @@ -1,9 +1,5 @@ package com.cosium.spring.data.jpa.entity.graph.repository.sample; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; import java.util.List; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; @@ -34,4 +30,9 @@ public String getEntityGraphName() { public List getEntityGraphAttributePaths() { return entityGraph.getEntityGraphAttributePaths(); } + + @Override + public boolean isOptional() { + return false; + } } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java index f5944e5..3a2b165 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java @@ -33,4 +33,9 @@ public EntityGraphType getEntityGraphType() { public List getEntityGraphAttributePaths() { return null; } + + @Override + public boolean isOptional() { + return false; + } } From b382aaf960bfd2175d5199b8b589907bf9cbe525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 10:33:07 +0100 Subject: [PATCH 60/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.10 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b954e93..df8a5af 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.10-SNAPSHOT + 1.10.10 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.10 From b4a963cfabe4a7fd6aa1324b235890157708cced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 10:33:07 +0100 Subject: [PATCH 61/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index df8a5af..b701376 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.10 + 1.10.11-SNAPSHOT 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.10 + HEAD From 6f7caeca50976e5cf091e4c759cd0eed931cdc8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 10:34:26 +0100 Subject: [PATCH 62/81] Bump to 1.10.10 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2633cec..ddafd24 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.09 + 1.10.10 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From 9d483347eecb4c4e52be2a8e84bbb702b40bd85b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 12:27:09 +0100 Subject: [PATCH 63/81] Primary EntityGraph should override any EntityGraph query hint (cherry picked from commit ad78bed) --- .../repository/support/EntityGraphBean.java | 11 +++- ...itoryEntityManagerEntityGraphInjector.java | 2 +- .../RepositoryMethodEntityGraphExtractor.java | 30 ++++----- .../RepositoryQueryEntityGraphInjector.java | 2 +- .../JpaEntityGraphRepositoryTest.java | 54 +++------------- ...aEntityGraphSpecificationExecutorTest.java | 62 +++++++++++++++++++ .../sample/EntityGraphSpecification.java | 10 ++- 7 files changed, 106 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java index 240aefe..bc1f0cf 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphBean.java @@ -17,9 +17,10 @@ class EntityGraphBean { private final Class domainClass; private final ResolvableType repositoryMethodReturnType; private final boolean optional; + private final boolean primary; private final boolean valid; - public EntityGraphBean(JpaEntityGraph jpaEntityGraph, Class domainClass, ResolvableType repositoryMethodReturnType, boolean optional) { + public EntityGraphBean(JpaEntityGraph jpaEntityGraph, Class domainClass, ResolvableType repositoryMethodReturnType, boolean optional, boolean primary) { Assert.notNull(jpaEntityGraph); Assert.notNull(domainClass); Assert.notNull(repositoryMethodReturnType); @@ -28,6 +29,7 @@ public EntityGraphBean(JpaEntityGraph jpaEntityGraph, Class domainClass, Reso this.domainClass = domainClass; this.repositoryMethodReturnType = repositoryMethodReturnType; this.optional = optional; + this.primary = primary; this.valid = computeValidity(); } @@ -72,6 +74,13 @@ public boolean isValid() { return valid; } + /** + * @return True if this EntityGraph is a primary one. Default EntityGraph is an example of non primary EntityGraph. + */ + public boolean isPrimary() { + return primary; + } + @Override public String toString() { return MoreObjects.toStringHelper(this) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java index 43eb109..852dde0 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryEntityManagerEntityGraphInjector.java @@ -103,7 +103,7 @@ private void addEntityGraphToFindMethodQueryHints(EntityGraphBean entityGraphCan LOG.trace("No query hints passed to the find method."); return; } - if (entityGraphCandidate.isOptional() && QueryHintsUtils.containsEntityGraph(queryProperties)) { + if (!entityGraphCandidate.isPrimary() && QueryHintsUtils.containsEntityGraph(queryProperties)) { LOG.trace("The query hints passed with the find method already hold an entity graph. Overriding aborted because the candidate EntityGraph is optional."); return; } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index 5c1cb5b..f376b7b 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -86,7 +86,7 @@ private EntityGraph findDefaultEntityGraph(EntityManager entityManager) { if (defaultEntityGraph != null) { throw new MultipleDefaultEntityGraphException(entityGraph.getName(), defaultEntityGraph.getEntityGraphName()); } - defaultEntityGraph = EntityGraphUtils.fromName(entityGraph.getName()); + defaultEntityGraph = EntityGraphUtils.fromName(entityGraph.getName(), true); } } return defaultEntityGraph; @@ -108,8 +108,6 @@ public Object invoke(MethodInvocation invocation) throws Throwable { providedEntityGraph = newEntityGraph; } - boolean emptyEntityGraph = isEmpty(providedEntityGraph); - Class implementationClass; if (invocation instanceof ReflectiveMethodInvocation) { implementationClass = ((ReflectiveMethodInvocation) invocation).getProxy().getClass(); @@ -118,9 +116,8 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } EntityGraphBean entityGraphCandidate = buildEntityGraphCandidate( - emptyEntityGraph ? defaultEntityGraph : providedEntityGraph, - ResolvableType.forMethodReturnType(invocation.getMethod(), implementationClass), - emptyEntityGraph || providedEntityGraph.isOptional() + providedEntityGraph, + ResolvableType.forMethodReturnType(invocation.getMethod(), implementationClass) ); if (entityGraphCandidate != null && !entityGraphCandidate.isValid()) { @@ -144,15 +141,20 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } } - private EntityGraphBean buildEntityGraphCandidate(EntityGraph entityGraph, ResolvableType returnType, boolean optional) { - if (entityGraph == null) { + private EntityGraphBean buildEntityGraphCandidate(EntityGraph providedEntityGraph, ResolvableType returnType) { + boolean isPrimary = true; + if (isEmpty(providedEntityGraph)) { + providedEntityGraph = defaultEntityGraph; + isPrimary = false; + } + if (providedEntityGraph == null) { return null; } - Assert.notNull(entityGraph.getEntityGraphType()); + Assert.notNull(providedEntityGraph.getEntityGraphType()); org.springframework.data.jpa.repository.EntityGraph.EntityGraphType type; - switch (entityGraph.getEntityGraphType()) { + switch (providedEntityGraph.getEntityGraphType()) { case FETCH: type = org.springframework.data.jpa.repository.EntityGraph.EntityGraphType.FETCH; break; @@ -160,17 +162,17 @@ private EntityGraphBean buildEntityGraphCandidate(EntityGraph entityGraph, Resol type = org.springframework.data.jpa.repository.EntityGraph.EntityGraphType.LOAD; break; default: - throw new RuntimeException("Unexpected entity graph type '" + entityGraph.getEntityGraphType() + "'"); + throw new RuntimeException("Unexpected entity graph type '" + providedEntityGraph.getEntityGraphType() + "'"); } - List attributePaths = entityGraph.getEntityGraphAttributePaths(); + List attributePaths = providedEntityGraph.getEntityGraphAttributePaths(); JpaEntityGraph jpaEntityGraph = new JpaEntityGraph( - StringUtils.hasText(entityGraph.getEntityGraphName()) ? entityGraph.getEntityGraphName() : domainClass.getName() + "-_-_-_-_-_-", + StringUtils.hasText(providedEntityGraph.getEntityGraphName()) ? providedEntityGraph.getEntityGraphName() : domainClass.getName() + "-_-_-_-_-_-", type, attributePaths != null ? attributePaths.toArray(new String[attributePaths.size()]) : null ); - return new EntityGraphBean(jpaEntityGraph, domainClass, returnType, optional); + return new EntityGraphBean(jpaEntityGraph, domainClass, returnType, providedEntityGraph.isOptional(), isPrimary); } } } diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java index 17fe161..55bb9ee 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java @@ -50,7 +50,7 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } private void addEntityGraphToQuery(Query query) { - if (entityGraphCandidate.isOptional() && QueryHintsUtils.containsEntityGraph(query.getHints())) { + if (!entityGraphCandidate.isPrimary() && QueryHintsUtils.containsEntityGraph(query.getHints())) { LOG.trace("The query hints passed with the find method already hold an entity graph. Overriding aborted because the candidate EntityGraph is optional."); return; } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index 6112d5c..2b17c9d 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -3,8 +3,6 @@ import static org.assertj.core.api.Assertions.*; import javax.inject.Inject; -import javax.persistence.Entity; -import javax.persistence.EntityManager; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; @@ -15,7 +13,6 @@ import com.cosium.spring.data.jpa.entity.graph.BaseTest; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; import com.cosium.spring.data.jpa.entity.graph.repository.exception.InapplicableEntityGraphException; -import com.cosium.spring.data.jpa.entity.graph.repository.exception.MultipleEntityGraphException; import com.cosium.spring.data.jpa.entity.graph.repository.sample.*; import com.github.springtestdbunit.annotation.DatabaseSetup; import com.github.springtestdbunit.annotation.DatabaseTearDown; @@ -63,6 +60,14 @@ public void given_brand_eg_when_findone_then_brand_should_be_loaded(){ assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); } + @Transactional + @Test + public void given_optional_brand_eg_when_findone_then_brand_should_be_loaded(){ + Product product = productRepository.findOne(1L, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG, true)); + assertThat(product).isNotNull(); + assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); + } + @Transactional @Test public void given_brand_eg_when_findByName_then_brand_should_be_loaded(){ @@ -152,47 +157,4 @@ public void given_products_and_ProductName_projection_when_findProductNameByName assertThat(productName).isNotNull(); } - @Transactional - @Test(expected = MultipleEntityGraphException.class) - public void given_products_when_findAllBySpec_with_two_non_empty_egs_then_it_should_fail(){ - productRepository.findAll(new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { - @Override - public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { - return null; - } - }, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); - } - - @Transactional - @Test(expected = MultipleEntityGraphException.class) - public void given_products_when_findAllBySpec_with_an_empty_eg_and_a_non_empty_one_then_it_should_fail(){ - productRepository.findAll(new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { - @Override - public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { - return null; - } - }, EntityGraphUtils.empty()); - } - - @Transactional - @Test(expected = MultipleEntityGraphException.class) - public void given_products_when_findAllBySpec_with_two_empty_eg_then_it_should_fail(){ - productRepository.findAll(new EmptyEntityGraphSpecification() { - @Override - public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { - return null; - } - }, EntityGraphUtils.empty()); - } - - @Transactional - @Test(expected = MultipleEntityGraphException.class) - public void given_products_when_findAllBySpec_with_a_non_empty_eg_and_an_empty_one_then_it_should_fail(){ - productRepository.findAll(new EmptyEntityGraphSpecification() { - @Override - public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { - return null; - } - }, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); - } } \ No newline at end of file diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphSpecificationExecutorTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphSpecificationExecutorTest.java index 78d0b89..488b5f5 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphSpecificationExecutorTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphSpecificationExecutorTest.java @@ -10,6 +10,9 @@ import java.util.List; import com.cosium.spring.data.jpa.entity.graph.BaseTest; +import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; +import com.cosium.spring.data.jpa.entity.graph.repository.exception.MultipleEntityGraphException; +import com.cosium.spring.data.jpa.entity.graph.repository.sample.EmptyEntityGraphSpecification; import com.cosium.spring.data.jpa.entity.graph.repository.sample.EntityGraphSpecification; import com.cosium.spring.data.jpa.entity.graph.repository.sample.Product; import com.cosium.spring.data.jpa.entity.graph.repository.sample.ProductRepository; @@ -46,4 +49,63 @@ public Predicate toPredicate(Root root, CriteriaQuery query, Criteri assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); } } + + @Transactional + @Test + public void given_brand_optional_eg_when_findbyspecification_implementing_eg_then_brand_should_be_loaded() { + List products = productRepository.findAll((Specification) new EntityGraphSpecification(Product.PRODUCT_BRAND_EG, true) { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return cb.equal(root.get("name"), "Product 2"); + } + }); + assertThat(products).hasSize(1); + for (Product product : products) { + assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); + } + } + + @Transactional + @Test(expected = MultipleEntityGraphException.class) + public void given_products_when_findAllBySpec_with_two_non_empty_egs_then_it_should_fail() { + productRepository.findAll(new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return null; + } + }, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + } + + @Transactional + @Test(expected = MultipleEntityGraphException.class) + public void given_products_when_findAllBySpec_with_an_empty_eg_and_a_non_empty_one_then_it_should_fail() { + productRepository.findAll(new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return null; + } + }, EntityGraphUtils.empty()); + } + + @Transactional + @Test(expected = MultipleEntityGraphException.class) + public void given_products_when_findAllBySpec_with_two_empty_eg_then_it_should_fail() { + productRepository.findAll(new EmptyEntityGraphSpecification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return null; + } + }, EntityGraphUtils.empty()); + } + + @Transactional + @Test(expected = MultipleEntityGraphException.class) + public void given_products_when_findAllBySpec_with_a_non_empty_eg_and_an_empty_one_then_it_should_fail() { + productRepository.findAll(new EmptyEntityGraphSpecification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { + return null; + } + }, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + } } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java index 3a2b165..8eaf9bc 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/EntityGraphSpecification.java @@ -14,9 +14,15 @@ public abstract class EntityGraphSpecification implements Specification, EntityGraph { private final String entityGraphName; + private final boolean optional; - public EntityGraphSpecification(String entityGraphName) { + public EntityGraphSpecification(String entityGraphName, boolean optional) { this.entityGraphName = entityGraphName; + this.optional = optional; + } + + public EntityGraphSpecification(String entityGraphName) { + this(entityGraphName, false); } @Override @@ -36,6 +42,6 @@ public List getEntityGraphAttributePaths() { @Override public boolean isOptional() { - return false; + return optional; } } From 6f678c13c9451615c7e6f2759e759ff74c13c9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 12:28:04 +0100 Subject: [PATCH 64/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.11 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b701376..dba2a46 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.11-SNAPSHOT + 1.10.11 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.11 From 8a8198e514630b231583e0d8f6e61f82c08fd4df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 12:28:04 +0100 Subject: [PATCH 65/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index dba2a46..1b1d56e 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.11 + 1.10.12-SNAPSHOT 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.11 + HEAD From 69bdb1f5f11347b973fea39f3029b08e62ac999c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 28 Nov 2016 12:29:39 +0100 Subject: [PATCH 66/81] Bump to 1.10.11 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ddafd24..f2b00ed 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.10 + 1.10.11 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From 69e6945dfe4cbbb3f0a9774a1fd7773d33643daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 5 Dec 2016 11:20:04 +0100 Subject: [PATCH 67/81] Fix #1 EntityGraph applied on QueryDsl Pagination count query (cherry picked from commit 5cafb6b) --- .../support/CountQueryDetector.java | 48 +++++++++++++++++++ ...EntityGraphAwareQueryDslJpaRepository.java | 31 ++++++++++++ .../QueryDslJpaEntityGraphRepository.java | 4 +- .../RepositoryQueryEntityGraphInjector.java | 5 +- ...ityGraphQueryDslPredicateExecutorTest.java | 20 ++++++-- .../spring/data/jpa/entity/graph/dataset.xml | 10 ++++ 6 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/CountQueryDetector.java create mode 100644 src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphAwareQueryDslJpaRepository.java diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/CountQueryDetector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/CountQueryDetector.java new file mode 100644 index 0000000..187fbf6 --- /dev/null +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/CountQueryDetector.java @@ -0,0 +1,48 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.support; + + +import com.querydsl.jpa.JPQLQuery; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.core.NamedThreadLocal; + +/** + * Created on 05/12/16. + * + * @author Reda.Housni-Alaoui + */ +class CountQueryDetector implements MethodInterceptor { + + private static final CountQueryDetector INSTANCE = new CountQueryDetector(); + private static final String FETCH_METHOD_NAME_PREFIX = "fetch"; + + private static final NamedThreadLocal IS_COUNT_QUERY = new NamedThreadLocal("A thread local holding a boolean describing " + + "the fact that the current query is count query"); + + private CountQueryDetector(){ + + } + + static JPQLQuery proxy(JPQLQuery countQuery){ + ProxyFactory proxyFactory = new ProxyFactory(countQuery); + proxyFactory.addAdvice(INSTANCE); + return (JPQLQuery) proxyFactory.getProxy(); + } + + static boolean isCountQuery(){ + return IS_COUNT_QUERY.get() == null? false: IS_COUNT_QUERY.get(); + } + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + if(invocation.getMethod().getName().startsWith(FETCH_METHOD_NAME_PREFIX)){ + IS_COUNT_QUERY.set(true); + } + try{ + return invocation.proceed(); + } finally { + IS_COUNT_QUERY.set(false); + } + } +} diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphAwareQueryDslJpaRepository.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphAwareQueryDslJpaRepository.java new file mode 100644 index 0000000..9653396 --- /dev/null +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/EntityGraphAwareQueryDslJpaRepository.java @@ -0,0 +1,31 @@ +package com.cosium.spring.data.jpa.entity.graph.repository.support; + +import javax.persistence.EntityManager; +import java.io.Serializable; + +import com.querydsl.core.types.Predicate; +import com.querydsl.jpa.JPQLQuery; +import org.springframework.data.jpa.repository.support.JpaEntityInformation; +import org.springframework.data.jpa.repository.support.QueryDslJpaRepository; +import org.springframework.data.querydsl.EntityPathResolver; + +/** + * Created on 05/12/16. + * + * @author Reda.Housni-Alaoui + */ +class EntityGraphAwareQueryDslJpaRepository extends QueryDslJpaRepository { + + public EntityGraphAwareQueryDslJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager) { + super(entityInformation, entityManager); + } + + public EntityGraphAwareQueryDslJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager, EntityPathResolver resolver) { + super(entityInformation, entityManager, resolver); + } + + @Override + protected JPQLQuery createCountQuery(Predicate predicate) { + return CountQueryDetector.proxy(super.createCountQuery(predicate)); + } +} diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryDslJpaEntityGraphRepository.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryDslJpaEntityGraphRepository.java index 6105f1a..ff98722 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryDslJpaEntityGraphRepository.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryDslJpaEntityGraphRepository.java @@ -28,13 +28,13 @@ public class QueryDslJpaEntityGraphRepository public QueryDslJpaEntityGraphRepository(JpaEntityInformation entityInformation, EntityManager entityManager) { super(entityInformation, entityManager); - this.queryDslJpaRepositoryDelegate = new QueryDslJpaRepository((JpaEntityInformation) entityInformation, entityManager); + this.queryDslJpaRepositoryDelegate = new EntityGraphAwareQueryDslJpaRepository((JpaEntityInformation) entityInformation, entityManager); } public QueryDslJpaEntityGraphRepository(JpaEntityInformation entityInformation, EntityManager entityManager, EntityPathResolver resolver) { super(entityInformation, entityManager); - this.queryDslJpaRepositoryDelegate = new QueryDslJpaRepository(entityInformation, entityManager, resolver); + this.queryDslJpaRepositoryDelegate = new EntityGraphAwareQueryDslJpaRepository(entityInformation, entityManager, resolver); } @Override diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java index 55bb9ee..0645b1a 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryQueryEntityGraphInjector.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Map; -import com.cosium.spring.data.jpa.entity.graph.repository.exception.InapplicableEntityGraphException; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; @@ -50,6 +49,10 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } private void addEntityGraphToQuery(Query query) { + if (CountQueryDetector.isCountQuery()) { + LOG.trace("CountQuery detected."); + return; + } if (!entityGraphCandidate.isPrimary() && QueryHintsUtils.containsEntityGraph(query.getHints())) { LOG.trace("The query hints passed with the find method already hold an entity graph. Overriding aborted because the candidate EntityGraph is optional."); return; diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphQueryDslPredicateExecutorTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphQueryDslPredicateExecutorTest.java index 17b968d..59b84ee 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphQueryDslPredicateExecutorTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphQueryDslPredicateExecutorTest.java @@ -1,6 +1,6 @@ package com.cosium.spring.data.jpa.entity.graph.repository; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.*; import javax.inject.Inject; @@ -12,8 +12,11 @@ import com.cosium.spring.data.jpa.entity.graph.repository.sample.QProduct; import com.github.springtestdbunit.annotation.DatabaseSetup; import com.github.springtestdbunit.annotation.DatabaseTearDown; +import com.querydsl.core.types.Predicate; import org.hibernate.Hibernate; import org.junit.Test; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.transaction.annotation.Transactional; /** @@ -30,7 +33,7 @@ public class JpaEntityGraphQueryDslPredicateExecutorTest extends BaseTest { @Transactional @Test - public void given_null_eg_when_findone_then_then_brand_should_not_be_loaded(){ + public void given_null_eg_when_findone_then_brand_should_not_be_loaded(){ Product product = productRepository.findOne(QProduct.product.name.eq("Product 1"), (EntityGraph) null); assertThat(product).isNotNull(); assertThat(Hibernate.isInitialized(product.getBrand())).isFalse(); @@ -38,9 +41,20 @@ public void given_null_eg_when_findone_then_then_brand_should_not_be_loaded(){ @Transactional @Test - public void given_brand_eg_when_findone_then_then_brand_should_not_be_loaded(){ + public void given_brand_eg_when_findone_then_brand_should_be_loaded(){ Product product = productRepository.findOne(QProduct.product.name.eq("Product 1"), EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); assertThat(product).isNotNull(); assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); } + + @Transactional + @Test + public void given_brand_eg_when_findpage_then_brand_should_be_loaded(){ + Page productPage = productRepository.findAll((Predicate) null, new PageRequest(0, 10),EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + assertThat(productPage.getContent()).isNotEmpty(); + for(Product product: productPage.getContent()){ + assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); + } + } + } diff --git a/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml b/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml index 36d891e..a26fb53 100644 --- a/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml +++ b/src/test/resources/com/cosium/spring/data/jpa/entity/graph/dataset.xml @@ -9,4 +9,14 @@ + + + + + + + + + + \ No newline at end of file From 789cbd37c33555d7d763a062c2bf75c4ab61e5e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 5 Dec 2016 11:23:08 +0100 Subject: [PATCH 68/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.12 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1b1d56e..0c03ceb 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.12-SNAPSHOT + 1.10.12 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.12 From 4b92560290d84846de1cb9765fcab2e38064d393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 5 Dec 2016 11:23:08 +0100 Subject: [PATCH 69/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0c03ceb..87ef951 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.12 + 1.10.13-SNAPSHOT 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.12 + HEAD From 8394b6438b92b59a68c427f00422301259312250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 5 Dec 2016 11:26:25 +0100 Subject: [PATCH 70/81] Bump to 1.10.12 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f2b00ed..bebe75e 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.11 + 1.10.12 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From 9c76b47fca41ea3a6b53c07526f0c0b141121e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 5 Dec 2016 21:29:06 +0100 Subject: [PATCH 71/81] Add travis config --- .travis.yml | 5 +++++ src/site/resources/settings.xml | 27 +++++++++++++++++++++++++++ src/test/resources/logback-test.xml | 12 ++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 .travis.yml create mode 100644 src/site/resources/settings.xml create mode 100644 src/test/resources/logback-test.xml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..df7e20a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: java +jdk: + - openjdk7 +before_install: + - curl -o $HOME/.m2/settings.xml https://raw.githubusercontent.com/Cosium/spring-data-jpa-entity-graph/$TRAVIS_BRANCH/src/site/resources/settings.xml \ No newline at end of file diff --git a/src/site/resources/settings.xml b/src/site/resources/settings.xml new file mode 100644 index 0000000..3756550 --- /dev/null +++ b/src/site/resources/settings.xml @@ -0,0 +1,27 @@ + + + + + + default + + + central + central + http://repo1.maven.org/maven2 + + + spring-snapshot-local + spring-snapshot-local + https://repo.spring.io/libs-snapshot-local + + + + + + + default + + diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml new file mode 100644 index 0000000..c75d693 --- /dev/null +++ b/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file From 7b4f55503c69426d1fa7e89901ad62f7bef1a6ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Mon, 5 Dec 2016 21:31:52 +0100 Subject: [PATCH 72/81] Use oraclejdk8 (cherry picked from commit 7c2fd6b) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index df7e20a..cdbfdfa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: java jdk: - - openjdk7 + - oraclejdk8 before_install: - curl -o $HOME/.m2/settings.xml https://raw.githubusercontent.com/Cosium/spring-data-jpa-entity-graph/$TRAVIS_BRANCH/src/site/resources/settings.xml \ No newline at end of file From 2e704a20efbd2c558a37294b0f88cdd7426b1044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Tue, 6 Dec 2016 16:47:12 +0100 Subject: [PATCH 73/81] Fix #2 Wrong EntityGraph applied when nesting repositories method call (cherry picked from commit 2152a16) --- .../repository/support/QueryHintsUtils.java | 6 ++-- .../RepositoryMethodEntityGraphExtractor.java | 35 +++++++++++++++---- .../JpaEntityGraphCustomRepositoryTest.java | 18 +++++++++- ...ityGraphQueryDslPredicateExecutorTest.java | 4 +-- .../JpaEntityGraphRepositoryTest.java | 14 ++++---- ...aEntityGraphSpecificationExecutorTest.java | 12 +++---- .../entity/graph/repository/sample/Brand.java | 5 +++ .../graph/repository/sample/Product.java | 7 ++-- .../repository/sample/ProductRepository.java | 4 ++- .../sample/ProductRepositoryCustom.java | 4 +++ .../sample/ProductRepositoryImpl.java | 20 +++++++++++ 11 files changed, 99 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java index 5bbeebd..44a00c8 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/QueryHintsUtils.java @@ -17,9 +17,9 @@ class QueryHintsUtils { * @return True if the QueryHints already hold an EntityGraph */ static boolean containsEntityGraph(Map queryHints){ - return queryHints == null - || queryHints.containsKey(EntityGraph.EntityGraphType.FETCH.getKey()) - || queryHints.containsKey(EntityGraph.EntityGraphType.LOAD.getKey()); + return queryHints != null + && (queryHints.containsKey(EntityGraph.EntityGraphType.FETCH.getKey()) + || queryHints.containsKey(EntityGraph.EntityGraphType.LOAD.getKey())); } /** diff --git a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java index f376b7b..ed48895 100644 --- a/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java +++ b/src/main/java/com/cosium/spring/data/jpa/entity/graph/repository/support/RepositoryMethodEntityGraphExtractor.java @@ -32,8 +32,8 @@ class RepositoryMethodEntityGraphExtractor implements RepositoryProxyPostProcess private static final Logger LOG = LoggerFactory.getLogger(RepositoryMethodEntityGraphExtractor.class); - private static final ThreadLocal CURRENT_ENTITY_GRAPH = - new NamedThreadLocal("Thread local holding the current spring data jpa repository entity graph"); + private static final ThreadLocal CURRENT_REPOSITORY = + new NamedThreadLocal("Thread local holding the current repository"); private final EntityManager entityManager; @@ -47,7 +47,11 @@ public void postProcess(ProxyFactory factory, RepositoryInformation repositoryIn } static EntityGraphBean getCurrentJpaEntityGraph() { - return CURRENT_ENTITY_GRAPH.get(); + JpaEntityGraphMethodInterceptor currentRepository = CURRENT_REPOSITORY.get(); + if (currentRepository == null) { + return null; + } + return currentRepository.getCurrentJpaEntityGraph(); } /** @@ -68,6 +72,7 @@ private static class JpaEntityGraphMethodInterceptor implements MethodIntercepto private static final String DEFAULT_ENTITYGRAPH_NAME_SUFFIX = ".default"; private final Class domainClass; private final EntityGraph defaultEntityGraph; + private final ThreadLocal currentEntityGraph = new NamedThreadLocal("Thread local holding the current spring data jpa repository entity graph"); JpaEntityGraphMethodInterceptor(EntityManager entityManager, Class domainClass) { this.domainClass = domainClass; @@ -92,8 +97,22 @@ private EntityGraph findDefaultEntityGraph(EntityManager entityManager) { return defaultEntityGraph; } + EntityGraphBean getCurrentJpaEntityGraph() { + return currentEntityGraph.get(); + } + @Override public Object invoke(MethodInvocation invocation) throws Throwable { + JpaEntityGraphMethodInterceptor oldRepo = CURRENT_REPOSITORY.get(); + CURRENT_REPOSITORY.set(this); + try { + return doInvoke(invocation); + } finally { + CURRENT_REPOSITORY.set(oldRepo); + } + } + + private Object doInvoke(MethodInvocation invocation) throws Throwable { Object[] arguments = invocation.getArguments(); EntityGraph providedEntityGraph = null; for (Object argument : arguments) { @@ -129,14 +148,16 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } } - if (entityGraphCandidate != null) { - CURRENT_ENTITY_GRAPH.set(entityGraphCandidate); + EntityGraphBean oldEntityGraphCandidate = currentEntityGraph.get(); + boolean newEntityGraphCandidatePreValidated = entityGraphCandidate != null && (oldEntityGraphCandidate == null || !oldEntityGraphCandidate.isPrimary()); + if (newEntityGraphCandidatePreValidated) { + currentEntityGraph.set(entityGraphCandidate); } try { return invocation.proceed(); } finally { - if (entityGraphCandidate != null) { - CURRENT_ENTITY_GRAPH.remove(); + if (newEntityGraphCandidatePreValidated) { + currentEntityGraph.set(oldEntityGraphCandidate); } } } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphCustomRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphCustomRepositoryTest.java index df47cf8..301e9d9 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphCustomRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphCustomRepositoryTest.java @@ -1,13 +1,18 @@ package com.cosium.spring.data.jpa.entity.graph.repository; +import static org.assertj.core.api.Assertions.assertThat; + import javax.inject.Inject; +import java.util.List; + import com.cosium.spring.data.jpa.entity.graph.BaseTest; import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; import com.cosium.spring.data.jpa.entity.graph.repository.sample.Product; import com.cosium.spring.data.jpa.entity.graph.repository.sample.ProductRepository; import com.github.springtestdbunit.annotation.DatabaseSetup; import com.github.springtestdbunit.annotation.DatabaseTearDown; +import org.hibernate.Hibernate; import org.junit.Test; import org.springframework.transaction.annotation.Transactional; @@ -26,7 +31,18 @@ public class JpaEntityGraphCustomRepositoryTest extends BaseTest { @Test @Transactional public void given_products_when_calling_customvoidmethod_with_eg_then_it_should_work(){ - productRepository.customMethod(EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + productRepository.customMethod(EntityGraphUtils.fromName(Product.BRAND_EG)); } + @Test + @Transactional + public void given_products_when_calling_customMethodCallingAnotherRepository_with_eg_then_brand_should_be_loaded(){ + List products = productRepository.customMethodCallingAnotherRepository(EntityGraphUtils.fromName(Product.BRAND_EG)); + assertThat(products).isNotEmpty(); + for(Product product: products){ + assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); + } + } + + } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphQueryDslPredicateExecutorTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphQueryDslPredicateExecutorTest.java index 59b84ee..2bdaa1a 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphQueryDslPredicateExecutorTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphQueryDslPredicateExecutorTest.java @@ -42,7 +42,7 @@ public void given_null_eg_when_findone_then_brand_should_not_be_loaded(){ @Transactional @Test public void given_brand_eg_when_findone_then_brand_should_be_loaded(){ - Product product = productRepository.findOne(QProduct.product.name.eq("Product 1"), EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + Product product = productRepository.findOne(QProduct.product.name.eq("Product 1"), EntityGraphUtils.fromName(Product.BRAND_EG)); assertThat(product).isNotNull(); assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); } @@ -50,7 +50,7 @@ public void given_brand_eg_when_findone_then_brand_should_be_loaded(){ @Transactional @Test public void given_brand_eg_when_findpage_then_brand_should_be_loaded(){ - Page productPage = productRepository.findAll((Predicate) null, new PageRequest(0, 10),EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + Page productPage = productRepository.findAll((Predicate) null, new PageRequest(0, 10),EntityGraphUtils.fromName(Product.BRAND_EG)); assertThat(productPage.getContent()).isNotEmpty(); for(Product product: productPage.getContent()){ assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java index 2b17c9d..3514f73 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphRepositoryTest.java @@ -55,7 +55,7 @@ public void given_empty_eg_when_findone_then_then_brand_should_not_be_loaded(){ @Transactional @Test public void given_brand_eg_when_findone_then_brand_should_be_loaded(){ - Product product = productRepository.findOne(1L, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + Product product = productRepository.findOne(1L, EntityGraphUtils.fromName(Product.BRAND_EG)); assertThat(product).isNotNull(); assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); } @@ -63,7 +63,7 @@ public void given_brand_eg_when_findone_then_brand_should_be_loaded(){ @Transactional @Test public void given_optional_brand_eg_when_findone_then_brand_should_be_loaded(){ - Product product = productRepository.findOne(1L, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG, true)); + Product product = productRepository.findOne(1L, EntityGraphUtils.fromName(Product.BRAND_EG, true)); assertThat(product).isNotNull(); assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); } @@ -71,7 +71,7 @@ public void given_optional_brand_eg_when_findone_then_brand_should_be_loaded(){ @Transactional @Test public void given_brand_eg_when_findByName_then_brand_should_be_loaded(){ - List products = productRepository.findByName("Product 1", EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + List products = productRepository.findByName("Product 1", EntityGraphUtils.fromName(Product.BRAND_EG)); assertThat(products).hasSize(1); for(Product product: products){ assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); @@ -81,7 +81,7 @@ public void given_brand_eg_when_findByName_then_brand_should_be_loaded(){ @Transactional @Test public void given_brand_eg_when_findAll_paginated_then_brand_should_be_loaded(){ - Page productPage = productRepository.findAll(new PageRequest(0, 10), EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + Page productPage = productRepository.findAll(new PageRequest(0, 10), EntityGraphUtils.fromName(Product.BRAND_EG)); assertThat(productPage.getContent()).isNotEmpty(); for(Product product: productPage.getContent()){ assertThat(Hibernate.isInitialized(product.getBrand())).isTrue(); @@ -91,7 +91,7 @@ public void given_brand_eg_when_findAll_paginated_then_brand_should_be_loaded(){ @Transactional @Test public void given_brand_eg_when_findAll_paginated_with_spec_then_brand_should_be_loaded(){ - Page productPage = productRepository.findAll(new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { + Page productPage = productRepository.findAll(new EntityGraphSpecification(Product.BRAND_EG) { @Override public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { return null; @@ -141,13 +141,13 @@ public void given_entity_without_default_eg_when_findall_then_it_should_work(){ @Transactional @Test(expected = InapplicableEntityGraphException.class) public void given_products_and_ProductName_projection_when_findProductNameByName_with_mandatory_eg_then_it_should_fail(){ - productRepository.findProductNameByName("Product 1", EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + productRepository.findProductNameByName("Product 1", EntityGraphUtils.fromName(Product.BRAND_EG)); } @Transactional @Test public void given_products_and_ProductName_projection_when_findProductNameByName_with_optional_eg_then_it_should_not_fail(){ - productRepository.findProductNameByName("Product 1", EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG, true)); + productRepository.findProductNameByName("Product 1", EntityGraphUtils.fromName(Product.BRAND_EG, true)); } @Transactional diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphSpecificationExecutorTest.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphSpecificationExecutorTest.java index 488b5f5..57d7034 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphSpecificationExecutorTest.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/JpaEntityGraphSpecificationExecutorTest.java @@ -38,7 +38,7 @@ public class JpaEntityGraphSpecificationExecutorTest extends BaseTest { @Transactional @Test public void given_brand_eg_when_findbyspecification_implementing_eg_then_brand_should_be_loaded() { - List products = productRepository.findAll((Specification) new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { + List products = productRepository.findAll((Specification) new EntityGraphSpecification(Product.BRAND_EG) { @Override public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { return cb.equal(root.get("name"), "Product 2"); @@ -53,7 +53,7 @@ public Predicate toPredicate(Root root, CriteriaQuery query, Criteri @Transactional @Test public void given_brand_optional_eg_when_findbyspecification_implementing_eg_then_brand_should_be_loaded() { - List products = productRepository.findAll((Specification) new EntityGraphSpecification(Product.PRODUCT_BRAND_EG, true) { + List products = productRepository.findAll((Specification) new EntityGraphSpecification(Product.BRAND_EG, true) { @Override public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { return cb.equal(root.get("name"), "Product 2"); @@ -68,18 +68,18 @@ public Predicate toPredicate(Root root, CriteriaQuery query, Criteri @Transactional @Test(expected = MultipleEntityGraphException.class) public void given_products_when_findAllBySpec_with_two_non_empty_egs_then_it_should_fail() { - productRepository.findAll(new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { + productRepository.findAll(new EntityGraphSpecification(Product.BRAND_EG) { @Override public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { return null; } - }, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + }, EntityGraphUtils.fromName(Product.BRAND_EG)); } @Transactional @Test(expected = MultipleEntityGraphException.class) public void given_products_when_findAllBySpec_with_an_empty_eg_and_a_non_empty_one_then_it_should_fail() { - productRepository.findAll(new EntityGraphSpecification(Product.PRODUCT_BRAND_EG) { + productRepository.findAll(new EntityGraphSpecification(Product.BRAND_EG) { @Override public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { return null; @@ -106,6 +106,6 @@ public void given_products_when_findAllBySpec_with_a_non_empty_eg_and_an_empty_o public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { return null; } - }, EntityGraphUtils.fromName(Product.PRODUCT_BRAND_EG)); + }, EntityGraphUtils.fromName(Product.BRAND_EG)); } } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Brand.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Brand.java index eee7acf..4855a1d 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Brand.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Brand.java @@ -7,9 +7,14 @@ * * @author Reda.Housni-Alaoui */ +@NamedEntityGraphs(value = { + @NamedEntityGraph(name = Brand.EMPTY_EG, attributeNodes = {}) +}) @Entity public class Brand { + public static final String EMPTY_EG = "Brand.empty"; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Access(value = AccessType.PROPERTY) diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java index efa4261..6e8f856 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/Product.java @@ -8,17 +8,18 @@ * @author Reda.Housni-Alaoui */ @NamedEntityGraphs(value = { - @NamedEntityGraph(name = "Product.default", attributeNodes = { + @NamedEntityGraph(name = Product.DEFAULT_EG, attributeNodes = { @NamedAttributeNode("maker") }), - @NamedEntityGraph(name = Product.PRODUCT_BRAND_EG, attributeNodes = { + @NamedEntityGraph(name = Product.BRAND_EG, attributeNodes = { @NamedAttributeNode("brand") }) }) @Entity public class Product { - public static final String PRODUCT_BRAND_EG = "Product.brand"; + public static final String DEFAULT_EG = "Product.default"; + public static final String BRAND_EG = "Product.brand"; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java index 63590c1..721bb06 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepository.java @@ -21,9 +21,11 @@ public interface ProductRepository List findByName(String name, EntityGraph entityGraph); + List findByBrand(Brand brand); + ProductName findProductNameByName(String name, EntityGraph entityGraph); - @org.springframework.data.jpa.repository.EntityGraph(value = Product.PRODUCT_BRAND_EG) + @org.springframework.data.jpa.repository.EntityGraph(value = Product.BRAND_EG) Product findByBarcode(String barcode); long countByName(String name); diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryCustom.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryCustom.java index 480a1fe..539d60f 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryCustom.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryCustom.java @@ -1,5 +1,7 @@ package com.cosium.spring.data.jpa.entity.graph.repository.sample; +import java.util.List; + import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; /** @@ -11,4 +13,6 @@ public interface ProductRepositoryCustom { void customMethod(EntityGraph entityGraph); + List customMethodCallingAnotherRepository(EntityGraph entityGraph); + } diff --git a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryImpl.java b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryImpl.java index 06248bf..e5ab3e2 100644 --- a/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryImpl.java +++ b/src/test/java/com/cosium/spring/data/jpa/entity/graph/repository/sample/ProductRepositoryImpl.java @@ -1,6 +1,12 @@ package com.cosium.spring.data.jpa.entity.graph.repository.sample; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; + import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph; +import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraphUtils; import org.springframework.stereotype.Component; /** @@ -11,9 +17,23 @@ @Component public class ProductRepositoryImpl implements ProductRepositoryCustom { + @Inject + private BrandRepository brandRepository; + @Inject + private ProductRepository productRepository; + @PersistenceContext + private EntityManager entityManager; + @Override public void customMethod(EntityGraph entityGraph) { } + @Override + public List customMethodCallingAnotherRepository(EntityGraph entityGraph) { + Brand brand = brandRepository.findOne(1L, EntityGraphUtils.fromName(Brand.EMPTY_EG)); + entityManager.flush(); + entityManager.clear(); + return productRepository.findByBrand(brand); + } } From 2363836bb00d933dd8cc44fe23d12f3473922052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Tue, 6 Dec 2016 17:01:27 +0100 Subject: [PATCH 74/81] [maven-release-plugin] prepare release spring-data-jpa-entity-graph-1.10.13 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 87ef951..1c56dcc 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.13-SNAPSHOT + 1.10.13 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - HEAD + spring-data-jpa-entity-graph-1.10.13 From 72f5b9d0d3eabe84d5fa291dc3a10e9e8416546d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Tue, 6 Dec 2016 17:01:27 +0100 Subject: [PATCH 75/81] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1c56dcc..20e81ae 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.13 + 1.10.14-SNAPSHOT 1.6 @@ -223,7 +223,7 @@ scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph scm:git:https://github.com/Cosium/spring-data-jpa-entity-graph https://github.com/Cosium/spring-data-jpa-entity-graph - spring-data-jpa-entity-graph-1.10.13 + HEAD From cd20329823c8d2219c5851427e7c46b0327ac00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Tue, 6 Dec 2016 17:03:33 +0100 Subject: [PATCH 76/81] Bump to 1.10.13 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bebe75e..397255f 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ spring-data-jpa-entity-graph | spring-data-jpa com.cosium.spring.data spring-data-jpa-entity-graph - 1.10.12 + 1.10.13 ``` 2. In your Spring configuration, set the repository factory bean class to `JpaEntityGraphRepositoryFactoryBean` : From cde7b67aab6b1d0bf530bce9c367bc16adc5ca58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Tue, 6 Dec 2016 17:21:24 +0100 Subject: [PATCH 77/81] Add badges --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 397255f..92d4a45 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +[![Travis branch](https://img.shields.io/travis/Cosium/spring-data-jpa-entity-graph/1.10.x.svg)](https://travis-ci.org/Cosium/spring-data-jpa-entity-graph) +[![Maven Central](https://img.shields.io/maven-central/v/com.cosium.spring.data/spring-data-jpa-entity-graph.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.cosium.spring.data%22%20AND%20a%3A%22spring-data-jpa-entity-graph%22) + # Spring Data JPA EntityGraph Today, [Spring Data JPA](https://github.com/spring-projects/spring-data-jpa) supports EntityGraph exlusively through annotations. From 189765c00053d498b8cf92b88e62f9603eca5175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 15 Dec 2016 17:43:26 +0100 Subject: [PATCH 78/81] Add codecov.io --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cdbfdfa..06a9297 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,4 +2,6 @@ language: java jdk: - oraclejdk8 before_install: - - curl -o $HOME/.m2/settings.xml https://raw.githubusercontent.com/Cosium/spring-data-jpa-entity-graph/$TRAVIS_BRANCH/src/site/resources/settings.xml \ No newline at end of file + - curl -o $HOME/.m2/settings.xml https://raw.githubusercontent.com/Cosium/spring-data-jpa-entity-graph/$TRAVIS_BRANCH/src/site/resources/settings.xml +after_success: + - bash <(curl -s https://codecov.io/bash) \ No newline at end of file From e6e0d95193fd16b5411446aeb64f900fc6d45d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 15 Dec 2016 19:17:27 +0100 Subject: [PATCH 79/81] Add codecov.io (cherry picked from commit 33de623) --- pom.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pom.xml b/pom.xml index 20e81ae..19e6469 100644 --- a/pom.xml +++ b/pom.xml @@ -175,6 +175,25 @@ + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 + + + + prepare-agent + + + + report + test + + report + + + + From 2a9a6da5f3a06bfd027cec16347ea2323252237d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 15 Dec 2016 19:23:14 +0100 Subject: [PATCH 80/81] Add codecov.io badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 92d4a45..bb4c924 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![Travis branch](https://img.shields.io/travis/Cosium/spring-data-jpa-entity-graph/1.10.x.svg)](https://travis-ci.org/Cosium/spring-data-jpa-entity-graph) +[![Codecov branch](https://img.shields.io/codecov/c/github/codecov/spring-data-jpa-entity-graph/1.10.x.svg)](https://codecov.io/gh/Cosium/spring-data-jpa-entity-graph) [![Maven Central](https://img.shields.io/maven-central/v/com.cosium.spring.data/spring-data-jpa-entity-graph.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.cosium.spring.data%22%20AND%20a%3A%22spring-data-jpa-entity-graph%22) # Spring Data JPA EntityGraph From d0a47e8818f1da1ec7eefdc17da60ab031a589d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Thu, 15 Dec 2016 19:28:36 +0100 Subject: [PATCH 81/81] Add codecov.io badge (cherry picked from commit 8c91188) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb4c924..8afe82e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Travis branch](https://img.shields.io/travis/Cosium/spring-data-jpa-entity-graph/1.10.x.svg)](https://travis-ci.org/Cosium/spring-data-jpa-entity-graph) -[![Codecov branch](https://img.shields.io/codecov/c/github/codecov/spring-data-jpa-entity-graph/1.10.x.svg)](https://codecov.io/gh/Cosium/spring-data-jpa-entity-graph) +[![Codecov branch](https://img.shields.io/codecov/c/github/Cosium/spring-data-jpa-entity-graph/1.10.x.svg)](https://codecov.io/gh/Cosium/spring-data-jpa-entity-graph) [![Maven Central](https://img.shields.io/maven-central/v/com.cosium.spring.data/spring-data-jpa-entity-graph.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.cosium.spring.data%22%20AND%20a%3A%22spring-data-jpa-entity-graph%22) # Spring Data JPA EntityGraph