Changed @Query based queries to use index parameters.
Using indexed parameters allows having a single method parameter to be bound to multiple placeholders.
This commit is contained in:
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.document.mongodb.repository;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||
@@ -32,10 +32,11 @@ import org.springframework.data.document.mongodb.query.Query;
|
||||
*/
|
||||
public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
|
||||
private static final Pattern PLACEHOLDER = Pattern.compile("\\?");
|
||||
private static final Pattern PLACEHOLDER = Pattern.compile("\\?(\\d+)");
|
||||
private static final Logger LOG = LoggerFactory.getLogger(StringBasedMongoQuery.class);
|
||||
|
||||
|
||||
private final String query;
|
||||
private final String fieldSpec;
|
||||
|
||||
/**
|
||||
* Creates a new {@link StringBasedMongoQuery}.
|
||||
@@ -46,6 +47,7 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
public StringBasedMongoQuery(MongoQueryMethod method, MongoTemplate template) {
|
||||
super(method, template);
|
||||
this.query = method.getAnnotatedQuery();
|
||||
this.fieldSpec = method.getFieldSpecification();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -57,19 +59,45 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
*/
|
||||
@Override
|
||||
protected Query createQuery(ConvertingParameterAccessor accessor) {
|
||||
|
||||
Matcher matcher = PLACEHOLDER.matcher(query);
|
||||
Iterator<Object> iterator = accessor.iterator();
|
||||
String result = null;
|
||||
|
||||
while (matcher.find()) {
|
||||
String group = matcher.group();
|
||||
result = query.replace(group, String.format("\"%s\"", iterator.next()));
|
||||
|
||||
String queryString = replacePlaceholders(query, accessor);
|
||||
|
||||
Query query = null;
|
||||
|
||||
if (fieldSpec != null) {
|
||||
String fieldString = replacePlaceholders(fieldSpec, accessor);
|
||||
query = new BasicQuery(queryString, fieldString);
|
||||
} else {
|
||||
query = new BasicQuery(queryString);
|
||||
}
|
||||
|
||||
Query query = new BasicQuery(result);
|
||||
|
||||
LOG.debug("Created query {}", query.getQueryObject());
|
||||
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
private String replacePlaceholders(String input, ConvertingParameterAccessor accessor) {
|
||||
|
||||
Matcher matcher = PLACEHOLDER.matcher(input);
|
||||
String result = null;
|
||||
|
||||
while (matcher.find()) {
|
||||
String group = matcher.group();
|
||||
int index = Integer.parseInt(matcher.group(1));
|
||||
result = input.replace(group, getParameterWithIndex(accessor, index));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private String getParameterWithIndex(ConvertingParameterAccessor accessor, int index) {
|
||||
Object parameter = accessor.getBindableValue(index);
|
||||
if (parameter instanceof String || parameter.getClass().isEnum()) {
|
||||
return String.format("\"%s\"", parameter);
|
||||
} else if (parameter instanceof ObjectId){
|
||||
return String.format("{ '$oid' : '%s' }", parameter);
|
||||
}
|
||||
|
||||
return parameter.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void finsPersonsByFirstname() {
|
||||
public void findsPersonsByFirstname() {
|
||||
|
||||
List<Person> result = repository.findByThePersonsFirstname("Leroi");
|
||||
assertThat(result.size(), is(1));
|
||||
|
||||
@@ -44,7 +44,7 @@ public interface PersonRepository extends MongoRepository<Person, String> {
|
||||
* @param firstname
|
||||
* @return
|
||||
*/
|
||||
@Query("{ 'firstname' : ? }")
|
||||
@Query("{ 'firstname' : ?0 }")
|
||||
List<Person> findByThePersonsFirstname(String firstname);
|
||||
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class StringBasedMongoQueryUnitTests {
|
||||
public void testname() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findByLastname", String.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, Person.class);
|
||||
StringBasedMongoQuery mongoQuery = new StringBasedMongoQuery(queryMethod, template);
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
|
||||
@@ -64,7 +64,7 @@ public class StringBasedMongoQueryUnitTests {
|
||||
|
||||
private interface SampleRepository {
|
||||
|
||||
@Query("{ 'lastname' : ? }")
|
||||
@Query("{ 'lastname' : ?0 }")
|
||||
Person findByLastname(String lastname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.springframework.data.repository.query.ParameterAccessor;
|
||||
*/
|
||||
class StubParameterAccessor implements ParameterAccessor {
|
||||
|
||||
private final Object[] values;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConvertingParameterAccessor} backed by a {@link StubParameterAccessor} simply returning the
|
||||
* given parameters converted but unfiltered.
|
||||
@@ -42,11 +44,7 @@ class StubParameterAccessor implements ParameterAccessor {
|
||||
|
||||
return new ConvertingParameterAccessor(converter, new StubParameterAccessor(parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Object[] values;
|
||||
|
||||
|
||||
public StubParameterAccessor(Object... values) {
|
||||
this.values = values;
|
||||
@@ -60,6 +58,13 @@ class StubParameterAccessor implements ParameterAccessor {
|
||||
public Pageable getPageable() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getBindableParameter(int)
|
||||
*/
|
||||
public Object getBindableValue(int index) {
|
||||
return values[index];
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
|
||||
Reference in New Issue
Block a user