DATAMONGO-1726 - Add oneValue() and firstValue() to FluentMongoOperations returning nullable types.

We leave the choice of using Optional open by also providing terminating find operation methods that return null instead of Optional.

Original pull request: #475.
This commit is contained in:
Christoph Strobl
2017-06-29 22:12:31 +02:00
committed by Mark Paluch
parent 3ac379a4b8
commit b9282c8d32
3 changed files with 50 additions and 7 deletions

View File

@@ -73,14 +73,33 @@ public interface ExecutableFindOperation {
* @return {@link Optional#empty()} if no match found. * @return {@link Optional#empty()} if no match found.
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one match found. * @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one match found.
*/ */
Optional<T> one(); default Optional<T> one() {
return Optional.ofNullable(oneValue());
}
/**
* Get exactly zero or one result.
*
* @return {@literal null} if no match found.
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one match found.
*/
T oneValue();
/** /**
* Get the first or no result. * Get the first or no result.
* *
* @return {@link Optional#empty()} if no match found. * @return {@link Optional#empty()} if no match found.
*/ */
Optional<T> first(); default Optional<T> first() {
return Optional.ofNullable(firstValue());
}
/**
* Get the first or no result.
*
* @return {@literal null} if no match found.
*/
T firstValue();
/** /**
* Get all matching elements. * Get all matching elements.

View File

@@ -104,27 +104,27 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
} }
@Override @Override
public Optional<T> one() { public T oneValue() {
List<T> result = doFind(new DelegatingQueryCursorPreparer(getCursorPreparer(query, null)).limit(2)); List<T> result = doFind(new DelegatingQueryCursorPreparer(getCursorPreparer(query, null)).limit(2));
if (ObjectUtils.isEmpty(result)) { if (ObjectUtils.isEmpty(result)) {
return Optional.empty(); return null;
} }
if (result.size() > 1) { if (result.size() > 1) {
throw new IncorrectResultSizeDataAccessException("Query " + asString() + " returned non unique result.", 1); throw new IncorrectResultSizeDataAccessException("Query " + asString() + " returned non unique result.", 1);
} }
return Optional.of(result.iterator().next()); return result.iterator().next();
} }
@Override @Override
public Optional<T> first() { public T firstValue() {
List<T> result = doFind(new DelegatingQueryCursorPreparer(getCursorPreparer(query, null)).limit(1)); List<T> result = doFind(new DelegatingQueryCursorPreparer(getCursorPreparer(query, null)).limit(1));
return ObjectUtils.isEmpty(result) ? Optional.empty() : Optional.of(result.iterator().next()); return ObjectUtils.isEmpty(result) ? null : result.iterator().next();
} }
@Override @Override

View File

@@ -140,6 +140,30 @@ public class ExecutableFindOperationSupportTests {
template.query(Person.class).matching(query(where("firstname").in("han", "luke"))).one(); template.query(Person.class).matching(query(where("firstname").in("han", "luke"))).one();
} }
@Test // DATAMONGO-1726
public void findByReturningOneValue() {
assertThat(template.query(Person.class).matching(query(where("firstname").is("luke"))).oneValue()).isEqualTo(luke);
}
@Test(expected = IncorrectResultSizeDataAccessException.class) // DATAMONGO-1726
public void findByReturningOneValueButTooManyResults() {
template.query(Person.class).matching(query(where("firstname").in("han", "luke"))).oneValue();
}
@Test // DATAMONGO-1726
public void findByReturningFirstValue() {
assertThat(template.query(Person.class).matching(query(where("firstname").is("luke"))).firstValue())
.isEqualTo(luke);
}
@Test // DATAMONGO-1726
public void findByReturningFirstValueForManyResults() {
assertThat(template.query(Person.class).matching(query(where("firstname").in("han", "luke"))).firstValue())
.isIn(han, luke);
}
@Test // DATAMONGO-1563 @Test // DATAMONGO-1563
public void streamAll() { public void streamAll() {