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); + } +}