From b1f5691373282f71f8311d51674008eb1085d33e 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 | 14 ++--- .../ParameterExpressionProviderTests.java | 51 +++++++++++++++++++ 2 files changed, 59 insertions(+), 6 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 507663265..f1001acc9 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 @@ -40,6 +40,7 @@ import org.springframework.data.repository.query.parser.Part; 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}. @@ -233,7 +234,7 @@ public class JpaQueryCreator extends AbstractQueryCreator, * * @author Oliver Gierke */ - private static class ParameterExpressionProvider { + static class ParameterExpressionProvider { private final CriteriaBuilder builder; private final Iterator parameters; @@ -285,10 +286,12 @@ public class JpaQueryCreator extends AbstractQueryCreator, * @param type must not be {@literal null}. * @return */ + @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); } /** @@ -299,14 +302,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); + } +}