DATAMONGO-1394 - Support identifier references on Querydsl expressions for DBRefs.

We now allow direct usage path.eq(…) on id properties of db referenced objects. This allows to write the query as person.coworker.id.eq(coworker.getId()) instead of person.coworker.eq(coworker). This helps building the query using just the plain id not having to actually create new object wrapping it.

Original pull request: #373.
This commit is contained in:
Christoph Strobl
2016-03-09 16:56:59 +01:00
committed by Oliver Gierke
parent 5a8e4f3dae
commit c14c42fb0c
2 changed files with 100 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 the original author or authors.
* Copyright 2011-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,9 @@ import org.springframework.util.Assert;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
import com.querydsl.core.types.Constant;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.Operation;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.PathType;
@@ -100,7 +103,6 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
if (ID_KEY.equals(key)) {
return mapper.getMappedObject(super.asDBObject(key, value), null);
}
return super.asDBObject(key, value instanceof Pattern ? value : converter.convertToMongoType(value));
}
@@ -111,7 +113,7 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
@Override
protected boolean isReference(Path<?> path) {
MongoPersistentProperty property = getPropertyFor(path);
MongoPersistentProperty property = getPropertyForPotentialDbRef(path);
return property == null ? false : property.isAssociation();
}
@@ -121,7 +123,50 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
*/
@Override
protected DBRef asReference(Object constant) {
return converter.toDBRef(constant, null);
return asReference(constant, null);
}
protected DBRef asReference(Object constant, Path<?> path) {
return converter.toDBRef(constant, getPropertyForPotentialDbRef(path));
}
@Override
protected String asDBKey(Operation<?> expr, int index) {
Expression<?> arg = expr.getArg(index);
if (arg instanceof Path) {
Path<?> path = (Path<?>) arg;
if (isReference(path)) {
MongoPersistentProperty property = getPropertyFor(path);
if (property.isIdProperty()) {
return super.asDBKey(expr, index).replaceAll("." + ID_KEY + "$", "");
}
}
}
return super.asDBKey(expr, index);
}
/*
* (non-Javadoc)
* @see com.querydsl.mongodb.MongodbSerializer#convert(com.querydsl.core.types.Path, com.querydsl.core.types.Constant)
*/
protected Object convert(Path<?> path, Constant<?> constant) {
if (isReference(path)) {
MongoPersistentProperty property = getPropertyFor(path);
if (property.isIdProperty()) {
return asReference(constant.getConstant(), path.getMetadata().getParent());
}
return asReference(constant.getConstant(), path);
}
return super.convert(path, constant);
}
private MongoPersistentProperty getPropertyFor(Path<?> path) {
@@ -135,4 +180,26 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(parent.getType());
return entity != null ? entity.getPersistentProperty(path.getMetadata().getName()) : null;
}
/**
* Checks the given {@literal path} for referencing the {@literal id} property of a {@link DBRef} referenced object.
* If so it returns the referenced {@link MongoPersistentProperty} of the {@link DBRef} instead of the {@literal id}
* property.
*
* @param path
* @return
*/
private MongoPersistentProperty getPropertyForPotentialDbRef(Path<?> path) {
if (path == null) {
return null;
}
MongoPersistentProperty property = getPropertyFor(path);
if (property != null && property.isIdProperty() && path.getMetadata() != null
&& path.getMetadata().getParent() != null) {
return getPropertyFor(path.getMetadata().getParent());
}
return property;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2014 the original author or authors.
* Copyright 2011-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.Person;
import org.springframework.data.mongodb.repository.QPerson;
import org.springframework.data.mongodb.repository.User;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -43,6 +44,7 @@ public class QuerydslRepositorySupportTests {
@Autowired MongoOperations operations;
Person person;
QuerydslRepositorySupport repoSupport;
@Before
public void setUp() {
@@ -50,6 +52,8 @@ public class QuerydslRepositorySupportTests {
operations.remove(new Query(), Person.class);
person = new Person("Dave", "Matthews");
operations.save(person);
repoSupport = new QuerydslRepositorySupport(operations) {};
}
@Test
@@ -72,10 +76,32 @@ public class QuerydslRepositorySupportTests {
operations.save(person);
QPerson p = QPerson.person;
QuerydslRepositorySupport support = new QuerydslRepositorySupport(operations) {};
SpringDataMongodbQuery<Person> query = support.from(p).where(p.skills.any().in("guitarist"));
SpringDataMongodbQuery<Person> query = repoSupport.from(p).where(p.skills.any().in("guitarist"));
assertThat(query.fetchOne(), is(person));
}
/**
* @see DATAMONGO-1394
*/
@Test
public void shouldAllowDbRefAgainstIdProperty() {
User bart = new User();
bart.setUsername("bart@simpson.com");
operations.save(bart);
person.setCoworker(bart);
operations.save(person);
QPerson p = QPerson.person;
SpringDataMongodbQuery<Person> queryUsingIdField = repoSupport.from(p).where(p.coworker.id.eq(bart.getId()));
SpringDataMongodbQuery<Person> queryUsingRefObject = repoSupport.from(p).where(p.coworker.eq(bart));
assertThat(queryUsingIdField.fetchOne(), equalTo(person));
assertThat(queryUsingIdField.fetchOne(), equalTo(queryUsingRefObject.fetchOne()));
}
}