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:
Oliver Gierke
2011-03-01 21:16:55 +01:00
parent 9e77e85854
commit 6f12450be6
5 changed files with 56 additions and 23 deletions

View File

@@ -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();
}
}

View File

@@ -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));

View File

@@ -44,7 +44,7 @@ public interface PersonRepository extends MongoRepository<Person, String> {
* @param firstname
* @return
*/
@Query("{ 'firstname' : ? }")
@Query("{ 'firstname' : ?0 }")
List<Person> findByThePersonsFirstname(String firstname);

View File

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

View File

@@ -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)