From 9bf6703c63e85178a53a3bc46231ff44a3a6c570 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 6 Sep 2011 11:49:07 +0200 Subject: [PATCH] DATADOC-99 - ParameterExpressionProvider now uses parameter type instead of handed in type if assignable. JpaQueryCreator hands Comparable into ParameterExpressionProvider to create ParameterExpression instances for Comparables. The ParameterExpressionProvider in turn now inspects the actual Parameter type and hand this one into the builder in case it's assignable (read: more concrete) to the given type requested. --- .../jpa/repository/query/JpaQueryCreator.java | 16 +++--- .../ParameterExpressionProviderTests.java | 51 +++++++++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 src/test/java/org/springframework/data/jpa/repository/query/ParameterExpressionProviderTests.java diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryCreator.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryCreator.java index cec67c314..fea701b0f 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryCreator.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryCreator.java @@ -41,6 +41,7 @@ import org.springframework.data.repository.query.parser.Part.Type; import org.springframework.data.repository.query.parser.PartTree; import org.springframework.data.repository.query.parser.Property; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; /** * Query creator to create a {@link CriteriaQuery} from a {@link PartTree}. @@ -204,7 +205,7 @@ public class JpaQueryCreator extends AbstractQueryCreator, * * @author Oliver Gierke */ - private static class ParameterExpressionProvider { + static class ParameterExpressionProvider { private final CriteriaBuilder builder; private final Iterator parameters; @@ -256,10 +257,12 @@ public class JpaQueryCreator extends AbstractQueryCreator, * @param type must not be {@literal null}. * @return */ - public ParameterExpression next(Class type) { + @SuppressWarnings("unchecked") + public ParameterExpression next(Class type) { - parameters.next(); - return next(type, null); + Parameter parameter = parameters.next(); + Class typeToUse = ClassUtils.isAssignable(type, parameter.getType()) ? parameter.getType() : type; + return (ParameterExpression) next(typeToUse, null); } /** @@ -270,14 +273,13 @@ public class JpaQueryCreator extends AbstractQueryCreator, * @param name * @return */ - @SuppressWarnings("unchecked") private ParameterExpression next(Class type, String name) { Assert.notNull(type); - ParameterExpression expression = name == null ? builder.parameter(type) : builder.parameter(type, name); + ParameterExpression expression = name == null ? builder.parameter(type) : builder.parameter(type, name); expressions.add(expression); - return (ParameterExpression) expression; + return expression; } } diff --git a/src/test/java/org/springframework/data/jpa/repository/query/ParameterExpressionProviderTests.java b/src/test/java/org/springframework/data/jpa/repository/query/ParameterExpressionProviderTests.java new file mode 100644 index 000000000..937a2f745 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/query/ParameterExpressionProviderTests.java @@ -0,0 +1,51 @@ +package org.springframework.data.jpa.repository.query; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.lang.reflect.Method; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.criteria.ParameterExpression; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.jpa.repository.query.JpaQueryCreator.ParameterExpressionProvider; +import org.springframework.data.repository.query.Parameters; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Integration tests for {@link ParameterExpressionProvider}. + * + * @author Oliver Gierke + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:infrastructure.xml") +public class ParameterExpressionProviderTests { + + @PersistenceContext + EntityManager em; + + /** + * @see DATADOC-99 + */ + @Test + @SuppressWarnings("rawtypes") + public void createsParameterExpressionWithMostConcreteType() throws Exception { + + Method method = SampleRepository.class.getMethod("findByIdGreaterThan", int.class); + Parameters parameters = new Parameters(method); + + ParameterExpressionProvider provider = new ParameterExpressionProvider(em.getCriteriaBuilder(), parameters); + ParameterExpression expression = provider.next(Comparable.class); + assertThat(expression.getParameterType(), is(typeCompatibleWith(int.class))); + } + + interface SampleRepository { + + User findByIdGreaterThan(int id); + } +}