Browse Source

#468 - Correctly map result of exists queries.

We now map results of exists queries to a boolean flag to ensure proper decoding. Previously, results were attempted to be mapped onto a primitive type which failed as there's no converter registered for Row to Boolean.
pull/1188/head
Mark Paluch 5 years ago
parent
commit
d3823947aa
No known key found for this signature in database
GPG Key ID: 51A00FA751B91849
  1. 36
      src/main/java/org/springframework/data/r2dbc/repository/query/AbstractR2dbcQuery.java
  2. 18
      src/main/java/org/springframework/data/r2dbc/repository/query/PartTreeR2dbcQuery.java
  3. 6
      src/main/java/org/springframework/data/r2dbc/repository/query/R2dbcQueryExecution.java
  4. 19
      src/main/java/org/springframework/data/r2dbc/repository/query/StringBasedR2dbcQuery.java
  5. 29
      src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java

36
src/main/java/org/springframework/data/r2dbc/repository/query/AbstractR2dbcQuery.java

@ -89,17 +89,21 @@ public abstract class AbstractR2dbcQuery implements RepositoryQuery { @@ -89,17 +89,21 @@ public abstract class AbstractR2dbcQuery implements RepositoryQuery {
return createQuery(parameterAccessor).flatMapMany(it -> executeQuery(parameterAccessor, it));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Publisher<?> executeQuery(RelationalParameterAccessor parameterAccessor, BindableQuery it) {
ResultProcessor processor = method.getResultProcessor().withDynamicProjection(parameterAccessor);
DatabaseClient.GenericExecuteSpec boundQuery = it.bind(databaseClient.sql(it));
FetchSpec<?> fetchSpec;
if (requiresMapping()) {
EntityRowMapper<?> rowMapper = new EntityRowMapper<>(resolveResultType(processor), converter);
FetchSpec<Object> fetchSpec;
if (isExistsQuery()) {
fetchSpec = (FetchSpec) boundQuery.map(row -> true);
} else if (requiresMapping()) {
EntityRowMapper rowMapper = new EntityRowMapper<>(resolveResultType(processor), converter);
fetchSpec = new FetchSpecAdapter<>(boundQuery.map(rowMapper));
} else {
fetchSpec = boundQuery.fetch();
fetchSpec = (FetchSpec) boundQuery.fetch();
}
SqlIdentifier tableName = method.getEntityInformation().getTableName();
@ -143,6 +147,14 @@ public abstract class AbstractR2dbcQuery implements RepositoryQuery { @@ -143,6 +147,14 @@ public abstract class AbstractR2dbcQuery implements RepositoryQuery {
return (q, t, c) -> q.rowsUpdated();
}
if (isCountQuery()) {
return (q, t, c) -> q.first().defaultIfEmpty(0L);
}
if (isExistsQuery()) {
return (q, t, c) -> q.first().defaultIfEmpty(false);
}
if (method.isCollectionQuery()) {
return (q, t, c) -> q.all();
}
@ -158,6 +170,22 @@ public abstract class AbstractR2dbcQuery implements RepositoryQuery { @@ -158,6 +170,22 @@ public abstract class AbstractR2dbcQuery implements RepositoryQuery {
*/
protected abstract boolean isModifyingQuery();
/**
* Returns whether the query should get a count projection applied.
*
* @return
* @since 1.2
*/
protected abstract boolean isCountQuery();
/**
* Returns whether the query should get an exists projection applied.
*
* @return
* @since 1.2
*/
protected abstract boolean isExistsQuery();
/**
* Creates a {@link BindableQuery} instance using the given {@link ParameterAccessor}
*

18
src/main/java/org/springframework/data/r2dbc/repository/query/PartTreeR2dbcQuery.java

@ -82,6 +82,24 @@ public class PartTreeR2dbcQuery extends AbstractR2dbcQuery { @@ -82,6 +82,24 @@ public class PartTreeR2dbcQuery extends AbstractR2dbcQuery {
return this.tree.isDelete();
}
/*
* (non-Javadoc)
* @see org.springframework.data.r2dbc.repository.query.AbstractR2dbcQuery#isCountQuery()
*/
@Override
protected boolean isCountQuery() {
return this.tree.isCountProjection();
}
/*
* (non-Javadoc)
* @see org.springframework.data.r2dbc.repository.query.AbstractR2dbcQuery#isExistsQuery()
*/
@Override
protected boolean isExistsQuery() {
return this.tree.isExistsProjection();
}
/*
* (non-Javadoc)
* @see org.springframework.data.r2dbc.repository.query.AbstractR2dbcQuery#createQuery(org.springframework.data.relational.repository.query.RelationalParameterAccessor)

6
src/main/java/org/springframework/data/r2dbc/repository/query/R2dbcQueryExecution.java

@ -41,7 +41,7 @@ import org.springframework.util.ClassUtils; @@ -41,7 +41,7 @@ import org.springframework.util.ClassUtils;
*/
interface R2dbcQueryExecution {
Publisher<?> execute(FetchSpec<?> query, Class<?> type, SqlIdentifier tableName);
Publisher<?> execute(FetchSpec<Object> query, Class<?> type, SqlIdentifier tableName);
/**
* An {@link R2dbcQueryExecution} that wraps the results of the given delegate with the given result processing.
@ -60,8 +60,8 @@ interface R2dbcQueryExecution { @@ -60,8 +60,8 @@ interface R2dbcQueryExecution {
* @see org.springframework.data.r2dbc.repository.query.R2dbcQueryExecution#execute(org.springframework.data.r2dbc.function.FetchSpec, java.lang.Class, java.lang.String)
*/
@Override
public Publisher<?> execute(FetchSpec<?> query, Class<?> type, SqlIdentifier tableName) {
return (Publisher<?>) this.converter.convert(this.delegate.execute(query, type, tableName));
public Publisher<Object> execute(FetchSpec<Object> query, Class<?> type, SqlIdentifier tableName) {
return (Publisher<Object>) this.converter.convert(this.delegate.execute(query, type, tableName));
}
}

19
src/main/java/org/springframework/data/r2dbc/repository/query/StringBasedR2dbcQuery.java

@ -112,6 +112,24 @@ public class StringBasedR2dbcQuery extends AbstractR2dbcQuery { @@ -112,6 +112,24 @@ public class StringBasedR2dbcQuery extends AbstractR2dbcQuery {
return getQueryMethod().isModifyingQuery();
}
/*
* (non-Javadoc)
* @see org.springframework.data.r2dbc.repository.query.AbstractR2dbcQuery#isCountQuery()
*/
@Override
protected boolean isCountQuery() {
return false;
}
/*
* (non-Javadoc)
* @see org.springframework.data.r2dbc.repository.query.AbstractR2dbcQuery#isExistsQuery()
*/
@Override
protected boolean isExistsQuery() {
return false;
}
/*
* (non-Javadoc)
* @see org.springframework.data.r2dbc.repository.query.AbstractR2dbcQuery#createQuery(org.springframework.data.relational.repository.query.RelationalParameterAccessor)
@ -133,6 +151,7 @@ public class StringBasedR2dbcQuery extends AbstractR2dbcQuery { @@ -133,6 +151,7 @@ public class StringBasedR2dbcQuery extends AbstractR2dbcQuery {
});
}
private Mono<R2dbcSpELExpressionEvaluator> getSpelEvaluator(RelationalParameterAccessor accessor) {
return evaluationContextProvider

29
src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java

@ -296,6 +296,33 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg @@ -296,6 +296,33 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
.verifyComplete();
}
@Test // gh-363
void derivedQueryWithCount() {
shouldInsertNewItems();
repository.countByNameContains("SCH") //
.as(StepVerifier::create) //
.assertNext(i -> assertThat(i).isEqualTo(2)) //
.verifyComplete();
}
@Test // gh-468
void derivedQueryWithExists() {
shouldInsertNewItems();
repository.existsByName("ABS") //
.as(StepVerifier::create) //
.expectNext(Boolean.FALSE) //
.verifyComplete();
repository.existsByName("SCHAUFELRADBAGGER") //
.as(StepVerifier::create) //
.expectNext(true) //
.verifyComplete();
}
@Test // gh-421
void shouldDeleteAllAndReturnCount() {
@ -345,6 +372,8 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg @@ -345,6 +372,8 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
Mono<Integer> deleteAllAndReturnCount();
Mono<Integer> countByNameContains(String namePart);
Mono<Boolean> existsByName(String name);
}
@Getter

Loading…
Cancel
Save