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.
This commit is contained in:
Oliver Gierke
2011-09-06 11:49:07 +02:00
parent a85c90b9fc
commit b1f5691373
2 changed files with 59 additions and 6 deletions

View File

@@ -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<CriteriaQuery<Object>,
*
* @author Oliver Gierke
*/
private static class ParameterExpressionProvider {
static class ParameterExpressionProvider {
private final CriteriaBuilder builder;
private final Iterator<Parameter> parameters;
@@ -285,10 +286,12 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
* @param type must not be {@literal null}.
* @return
*/
@SuppressWarnings("unchecked")
public <T> ParameterExpression<T> next(Class<T> type) {
parameters.next();
return next(type, null);
Parameter parameter = parameters.next();
Class<?> typeToUse = ClassUtils.isAssignable(type, parameter.getType()) ? parameter.getType() : type;
return (ParameterExpression<T>) next(typeToUse, null);
}
/**
@@ -299,14 +302,13 @@ public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<Object>,
* @param name
* @return
*/
@SuppressWarnings("unchecked")
private <T> ParameterExpression<T> next(Class<T> type, String name) {
Assert.notNull(type);
ParameterExpression<?> expression = name == null ? builder.parameter(type) : builder.parameter(type, name);
ParameterExpression<T> expression = name == null ? builder.parameter(type) : builder.parameter(type, name);
expressions.add(expression);
return (ParameterExpression<T>) expression;
return expression;
}
}
}

View File

@@ -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<? extends Comparable> expression = provider.next(Comparable.class);
assertThat(expression.getParameterType(), is(typeCompatibleWith(int.class)));
}
interface SampleRepository {
User findByIdGreaterThan(int id);
}
}