diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java index 6ee178bbb..9ca6ecec2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java @@ -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; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java index ccb848cb3..dc275d5c9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java @@ -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 query = support.from(p).where(p.skills.any().in("guitarist")); + SpringDataMongodbQuery 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 queryUsingIdField = repoSupport.from(p).where(p.coworker.id.eq(bart.getId())); + SpringDataMongodbQuery queryUsingRefObject = repoSupport.from(p).where(p.coworker.eq(bart)); + + assertThat(queryUsingIdField.fetchOne(), equalTo(person)); + assertThat(queryUsingIdField.fetchOne(), equalTo(queryUsingRefObject.fetchOne())); + } + }