From b89c297f4e658c94ae25ff8dd75c9783904d617e Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Mon, 11 Jun 2018 14:29:13 +0200 Subject: [PATCH] DATAJPA-1238 - Added test to verify improved behavior. Had to add special handling due to different interpretations of the JPA specification by Eclipselink and Hibernate. See also: https://github.com/javaee/jpa-spec/issues/169. Original pull request: #270. --- ...EclipseLinkQueryUtilsIntegrationTests.java | 8 +++- .../query/QueryUtilsIntegrationTests.java | 48 +++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkQueryUtilsIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkQueryUtilsIntegrationTests.java index 4b84acd30..9bba5e90b 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkQueryUtilsIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/EclipseLinkQueryUtilsIntegrationTests.java @@ -21,4 +21,10 @@ import org.springframework.test.context.ContextConfiguration; * @author Oliver Gierke */ @ContextConfiguration("classpath:eclipselink.xml") -public class EclipseLinkQueryUtilsIntegrationTests extends QueryUtilsIntegrationTests {} +public class EclipseLinkQueryUtilsIntegrationTests extends QueryUtilsIntegrationTests { + + int getNumberOfJoinsAfterCreatingAPath() { + return 1; + } + +} diff --git a/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsIntegrationTests.java index 6e708115e..9c559c300 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsIntegrationTests.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.*; import java.util.Collections; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import javax.persistence.Entity; import javax.persistence.EntityManager; @@ -80,8 +81,8 @@ public class QueryUtilsIntegrationTests { assertThat(from.getJoins()).hasSize(1); } - @Test // DATAJPA-401 - public void createsJoinForOptionalAssociation() { + @Test // DATAJPA-401, DATAJPA-1238 + public void createsJoinForNavigationAcrossOptionalAssociation() { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery query = builder.createQuery(User.class); @@ -89,7 +90,19 @@ public class QueryUtilsIntegrationTests { QueryUtils.toExpressionRecursively(root, PropertyPath.from("manager.firstname", User.class)); - assertThat(root.getJoins()).hasSize(1); + assertThat(getNonInnerJoins(root)).hasSize(1); + } + + @Test // DATAJPA-401, DATAJPA-1238 + public void doesNotCreateJoinForOptionalAssociationWithoutFurtherNavigation() { + + CriteriaBuilder builder = em.getCriteriaBuilder(); + CriteriaQuery query = builder.createQuery(User.class); + Root root = query.from(User.class); + + QueryUtils.toExpressionRecursively(root, PropertyPath.from("manager", User.class)); + + assertThat(getNonInnerJoins(root)).hasSize(0); } @Test // DATAJPA-401 @@ -169,6 +182,27 @@ public class QueryUtilsIntegrationTests { assertThat(orders).hasSize(1); } + /** + * This test documents an ambiguity in the JPA spec (or it's implementation in Hibernate vs EclipseLink) that we have + * to work around in the test {@link #doesNotCreateJoinForOptionalAssociationWithoutFurtherNavigation()}. See also: + * https://github.com/javaee/jpa-spec/issues/169 Compare to: {@link EclipseLinkQueryUtilsIntegrationTests} + */ + @Test // DATAJPA-1238 + public void demonstrateDifferentBehavorOfGetJoin() { + + CriteriaBuilder builder = em.getCriteriaBuilder(); + CriteriaQuery query = builder.createQuery(User.class); + Root root = query.from(User.class); + + root.get("manager"); + + assertThat(root.getJoins()).hasSize(getNumberOfJoinsAfterCreatingAPath()); + } + + int getNumberOfJoinsAfterCreatingAPath() { + return 0; + } + @Entity @SuppressWarnings("unused") static class Merchant { @@ -177,6 +211,14 @@ public class QueryUtilsIntegrationTests { @OneToMany Set employees; } + private Set> getNonInnerJoins(Root root) { + + return root.getJoins() // + .stream() // + .filter(j -> j.getJoinType() != JoinType.INNER) // + .collect(Collectors.toSet()); + } + @Entity @SuppressWarnings("unused") static class Employee {