From 1c8a55a081909ad68a3ebdf824987df77fa7bd81 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Fri, 6 May 2011 16:58:32 +0200 Subject: [PATCH] DATADOC-113 - NotNull and IsNull are now working for repositories. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed Criteria being able to create correct query for ….is(null). MongoQueryCreator now uses ….ne(…) instead of ….not().is(…) as this doesn't generate a correct query (see DATADOC-129). --- .../data/document/mongodb/query/Criteria.java | 11 +++-- .../mongodb/repository/MongoQueryCreator.java | 2 +- .../document/mongodb/query/CriteriaTests.java | 22 +++++++--- .../MongoQueryCreatorUnitTests.java | 42 +++++++++++-------- 4 files changed, 49 insertions(+), 28 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/query/Criteria.java index 05cedac8a..3ab683bad 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/query/Criteria.java @@ -29,6 +29,11 @@ import org.springframework.data.document.mongodb.geo.Point; import org.springframework.util.Assert; public class Criteria implements CriteriaDefinition { + + /** + * Custom "not-null" object as we have to be able to work with {@literal null} values as well. + */ + private static final Object NOT_SET = new Object(); private String key; @@ -36,7 +41,7 @@ public class Criteria implements CriteriaDefinition { private LinkedHashMap criteria = new LinkedHashMap(); - private Object isValue = null; + private Object isValue = NOT_SET; public Criteria(String key) { this.criteriaChain = new ArrayList(); @@ -81,7 +86,7 @@ public class Criteria implements CriteriaDefinition { * @return */ public Criteria is(Object o) { - if (isValue != null) { + if (isValue != NOT_SET) { throw new InvalidDocumentStoreApiUsageException( "Multiple 'is' values declared. You need to use 'and' with multiple criteria"); } @@ -394,7 +399,7 @@ public class Criteria implements CriteriaDefinition { } } DBObject queryCriteria = new BasicDBObject(); - if (isValue != null) { + if (isValue != NOT_SET) { queryCriteria.put(this.key, this.isValue); queryCriteria.putAll(dbo); } else { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java index 1497821de..6967e2142 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java @@ -140,7 +140,7 @@ class MongoQueryCreator extends AbstractQueryCreator { case BETWEEN: return criteria.gt(parameters.nextConverted()).lt(parameters.nextConverted()); case IS_NOT_NULL: - return criteria.not().is(null); + return criteria.ne(null); case IS_NULL: return criteria.is(null); case NOT_IN: diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/query/CriteriaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/query/CriteriaTests.java index 25c25e9a1..9109e23b3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/query/CriteriaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/query/CriteriaTests.java @@ -15,28 +15,38 @@ */ package org.springframework.data.document.mongodb.query; -import org.junit.Assert; +import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.*; import org.junit.Test; -import org.springframework.data.document.mongodb.query.Index.Duplicates; +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; public class CriteriaTests { @Test public void testSimpleCriteria() { Criteria c = new Criteria("name").is("Bubba"); - Assert.assertEquals("{ \"name\" : \"Bubba\"}", c.getCriteriaObject().toString()); + assertEquals("{ \"name\" : \"Bubba\"}", c.getCriteriaObject().toString()); } @Test public void testNotEqualCriteria() { Criteria c = new Criteria("name").ne("Bubba"); - Assert.assertEquals("{ \"name\" : { \"$ne\" : \"Bubba\"}}", c.getCriteriaObject().toString()); + assertEquals("{ \"name\" : { \"$ne\" : \"Bubba\"}}", c.getCriteriaObject().toString()); + } + + @Test + public void buildsIsNullCriteriaCorrectly() { + + DBObject reference = new BasicDBObject("name", null); + + Criteria criteria = new Criteria("name").is(null); + assertThat(criteria.getCriteriaObject(), is(reference)); } - @Test public void testChainedCriteria() { Criteria c = new Criteria("name").is("Bubba").and("age").lt(21); - Assert.assertEquals("{ \"name\" : \"Bubba\" , \"age\" : { \"$lt\" : 21}}", c.getCriteriaObject().toString()); + assertEquals("{ \"name\" : \"Bubba\" , \"age\" : { \"$lt\" : 21}}", c.getCriteriaObject().toString()); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java index ffa3c5cdf..ad4753d02 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java @@ -15,21 +15,24 @@ */ package org.springframework.data.document.mongodb.repository; +import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import static org.hamcrest.CoreMatchers.*; import static org.springframework.data.document.mongodb.repository.StubParameterAccessor.getAccessor; import java.lang.reflect.Method; -import java.util.List; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.springframework.data.document.mongodb.Person; import org.springframework.data.document.mongodb.convert.MongoConverter; +import org.springframework.data.document.mongodb.query.Criteria; +import org.springframework.data.document.mongodb.query.Query; import org.springframework.data.repository.query.parser.PartTree; import com.mongodb.BasicDBObject; @@ -44,8 +47,7 @@ import com.mongodb.DBObject; @RunWith(MockitoJUnitRunner.class) public class MongoQueryCreatorUnitTests { - Method findByFirstname; - Method findByFirstnameAndFriend; + Method findByFirstname, findByFirstnameAndFriend, findByFirstnameNotNull; @Mock MongoConverter converter; @@ -53,12 +55,6 @@ public class MongoQueryCreatorUnitTests { @Before public void setUp() throws SecurityException, NoSuchMethodException { - - findByFirstname = - Sample.class.getMethod("findByFirstname", String.class); - findByFirstnameAndFriend = - Sample.class.getMethod("findByFirstnameAndFriend", - String.class, Person.class); doAnswer(new Answer() { public Void answer(InvocationOnMock invocation) throws Throwable { @@ -66,7 +62,7 @@ public class MongoQueryCreatorUnitTests { dbObject.put("value", new BasicDBObject("value", "value")); return null; } - }).when(converter).write(any(), any(DBObject.class)); + }).when(converter).write(any(), Mockito.any(DBObject.class)); } @@ -86,12 +82,22 @@ public class MongoQueryCreatorUnitTests { Person.class), getAccessor(converter, "Oliver", new Person())); creator.createQuery(); } - - interface Sample { - - List findByFirstname(String firstname); - - - List findByFirstnameAndFriend(String firstname, Person friend); + + @Test + public void createsNotNullQueryCorrectly() { + + PartTree tree = new PartTree("findByFirstNameNotNull", Person.class); + Query query = new MongoQueryCreator(tree, getAccessor(converter)).createQuery(); + + assertThat(query.getQueryObject(), is(new Query(Criteria.where("firstName").ne(null)).getQueryObject())); + } + + @Test + public void createsIsNullQueryCorrectly() { + + PartTree tree = new PartTree("findByFirstNameIsNull", Person.class); + Query query = new MongoQueryCreator(tree, getAccessor(converter)).createQuery(); + + assertThat(query.getQueryObject(), is(new Query(Criteria.where("firstName").is(null)).getQueryObject())); } }