DATACASS-313 - Limit queried fields for projections.
We now limit the selected fields when using projections in repository query methods and by using query operations. Queries that return either a closed interface projection or DTO projection are inspected for the select fields and only these fields are included in the SELECT list.
This commit is contained in:
@@ -49,6 +49,7 @@ import org.springframework.data.cassandra.core.mapping.event.AfterLoadEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.AfterSaveEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.BeforeDeleteEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.BeforeSaveEvent;
|
||||
import org.springframework.data.cassandra.core.query.Columns;
|
||||
import org.springframework.data.cassandra.core.query.Query;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
@@ -322,8 +323,14 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
|
||||
<T> List<T> doSelect(Query query, Class<?> entityClass, CqlIdentifier tableName, Class<T> returnType) {
|
||||
|
||||
Function<Row, T> mapper = getMapper(entityClass, returnType, tableName);
|
||||
CassandraPersistentEntity<?> persistentEntity = getRequiredPersistentEntity(entityClass);
|
||||
|
||||
RegularStatement select = getStatementFactory().select(query, getRequiredPersistentEntity(entityClass), tableName);
|
||||
Columns columns = getStatementFactory().computeColumnsForProjection(query.getColumns(), persistentEntity,
|
||||
returnType);
|
||||
|
||||
Query queryToUse = query.columns(columns);
|
||||
|
||||
RegularStatement select = getStatementFactory().select(queryToUse, persistentEntity, tableName);
|
||||
|
||||
return getCqlOperations().query(select, (row, rowNum) -> mapper.apply(row));
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import org.springframework.data.cassandra.core.mapping.event.AfterLoadEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.AfterSaveEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.BeforeDeleteEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.BeforeSaveEvent;
|
||||
import org.springframework.data.cassandra.core.query.Columns;
|
||||
import org.springframework.data.cassandra.core.query.Query;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.SliceImpl;
|
||||
@@ -296,7 +297,14 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations, A
|
||||
|
||||
<T> Flux<T> doSelect(Query query, Class<?> entityClass, CqlIdentifier tableName, Class<T> returnType) {
|
||||
|
||||
RegularStatement select = getStatementFactory().select(query, getRequiredPersistentEntity(entityClass), tableName);
|
||||
CassandraPersistentEntity<?> persistentEntity = getRequiredPersistentEntity(entityClass);
|
||||
|
||||
Columns columns = getStatementFactory().computeColumnsForProjection(query.getColumns(), persistentEntity,
|
||||
returnType);
|
||||
|
||||
Query queryToUse = query.columns(columns);
|
||||
|
||||
RegularStatement select = getStatementFactory().select(queryToUse, persistentEntity, tableName);
|
||||
|
||||
Function<Row, T> mapper = getMapper(entityClass, returnType, tableName);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -27,6 +28,7 @@ import org.springframework.data.cassandra.core.cql.CqlIdentifier;
|
||||
import org.springframework.data.cassandra.core.cql.QueryOptionsUtil;
|
||||
import org.springframework.data.cassandra.core.cql.WriteOptions;
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.core.query.Columns;
|
||||
import org.springframework.data.cassandra.core.query.Columns.ColumnSelector;
|
||||
import org.springframework.data.cassandra.core.query.Columns.FunctionCall;
|
||||
import org.springframework.data.cassandra.core.query.Columns.Selector;
|
||||
@@ -46,7 +48,13 @@ import org.springframework.data.cassandra.core.query.Update.SetAtKeyOp;
|
||||
import org.springframework.data.cassandra.core.query.Update.SetOp;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.ProjectionInformation;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.datastax.driver.core.RegularStatement;
|
||||
import com.datastax.driver.core.Statement;
|
||||
@@ -75,6 +83,8 @@ public class StatementFactory {
|
||||
|
||||
private final UpdateMapper updateMapper;
|
||||
|
||||
private final ProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory();
|
||||
|
||||
/**
|
||||
* Create {@link StatementFactory} given {@link UpdateMapper}.
|
||||
*
|
||||
@@ -190,8 +200,8 @@ public class StatementFactory {
|
||||
return createSelect(query, entity, filter, selectors, tableName);
|
||||
}
|
||||
|
||||
private Select createSelect(Query query, CassandraPersistentEntity<?> entity, Filter filter,
|
||||
List<Selector> selectors, CqlIdentifier tableName) {
|
||||
private Select createSelect(Query query, CassandraPersistentEntity<?> entity, Filter filter, List<Selector> selectors,
|
||||
CqlIdentifier tableName) {
|
||||
|
||||
Sort sort = Optional.of(query.getSort()).map(querySort -> getQueryMapper().getMappedSort(querySort, entity))
|
||||
.orElse(Sort.unsorted());
|
||||
@@ -223,8 +233,8 @@ public class StatementFactory {
|
||||
|
||||
Selection selection = QueryBuilder.select();
|
||||
|
||||
selectors.forEach(selector ->
|
||||
selector.getAlias().map(CqlIdentifier::toCql).ifPresent(getSelection(selection, selector)::as));
|
||||
selectors.forEach(
|
||||
selector -> selector.getAlias().map(CqlIdentifier::toCql).ifPresent(getSelection(selection, selector)::as));
|
||||
select = selection.from(from.toCql());
|
||||
}
|
||||
|
||||
@@ -465,6 +475,43 @@ public class StatementFactory {
|
||||
return delete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the {@link Columns} to include type if the {@code returnType} is a {@literal DTO projection} or a
|
||||
* {@literal closed interface projection}.
|
||||
*
|
||||
* @param columns must not be {@literal null}.
|
||||
* @param persistentEntity must not be {@literal null}.
|
||||
* @param returnType must not be {@literal null}.
|
||||
* @return {@link Columns} with columns to be included.
|
||||
* @since 2.2
|
||||
*/
|
||||
Columns computeColumnsForProjection(Columns columns, PersistentEntity<?, ?> persistentEntity, Class<?> returnType) {
|
||||
|
||||
if (!columns.isEmpty() || ClassUtils.isAssignable(persistentEntity.getType(), returnType)) {
|
||||
return columns;
|
||||
}
|
||||
|
||||
Columns projectedColumns = Columns.empty();
|
||||
|
||||
if (returnType.isInterface()) {
|
||||
|
||||
ProjectionInformation projectionInformation = projectionFactory.getProjectionInformation(returnType);
|
||||
|
||||
if (projectionInformation.isClosed()) {
|
||||
|
||||
for (PropertyDescriptor inputProperty : projectionInformation.getInputProperties()) {
|
||||
projectedColumns = projectedColumns.include(inputProperty.getName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (PersistentProperty<?> property : persistentEntity) {
|
||||
projectedColumns = projectedColumns.include(property.getName());
|
||||
}
|
||||
}
|
||||
|
||||
return projectedColumns;
|
||||
}
|
||||
|
||||
private static Delete delete(List<String> columnNames, CqlIdentifier from, Filter filter) {
|
||||
|
||||
Delete select;
|
||||
@@ -538,7 +585,7 @@ public class StatementFactory {
|
||||
return QueryBuilder.containsKey(columnName, predicate.getValue());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Criteria %s %s %s not supported",
|
||||
columnName, predicate.getOperator(), predicate.getValue()));
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Criteria %s %s %s not supported", columnName, predicate.getOperator(), predicate.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,8 @@ public class PartTreeCassandraQuery extends AbstractCassandraQuery {
|
||||
return getQueryStatementCreator().exists(getStatementFactory(), getTree(), parameterAccessor);
|
||||
}
|
||||
|
||||
return getQueryStatementCreator().select(getStatementFactory(), getTree(), parameterAccessor);
|
||||
return getQueryStatementCreator().select(getStatementFactory(), getTree(), parameterAccessor,
|
||||
getQueryMethod().getResultProcessor());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -15,24 +15,26 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.cassandra.core.StatementFactory;
|
||||
import org.springframework.data.cassandra.core.cql.QueryOptions;
|
||||
import org.springframework.data.cassandra.core.cql.QueryOptionsUtil;
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.core.query.Columns;
|
||||
import org.springframework.data.cassandra.core.query.Query;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.repository.query.QueryCreationException;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.datastax.driver.core.RegularStatement;
|
||||
import com.datastax.driver.core.SimpleStatement;
|
||||
import com.datastax.driver.core.Statement;
|
||||
@@ -65,11 +67,19 @@ class QueryStatementCreator {
|
||||
* @param parameterAccessor must not be {@literal null}.
|
||||
* @return the {@literal SELECT} {@link Statement}.
|
||||
*/
|
||||
Statement select(StatementFactory statementFactory, PartTree tree,
|
||||
CassandraParameterAccessor parameterAccessor) {
|
||||
Statement select(StatementFactory statementFactory, PartTree tree, CassandraParameterAccessor parameterAccessor,
|
||||
ResultProcessor processor) {
|
||||
|
||||
Function<Query, Statement> function = query -> {
|
||||
|
||||
ReturnedType returnedType = processor.withDynamicProjection(parameterAccessor).getReturnedType();
|
||||
|
||||
if (returnedType.needsCustomConstruction()) {
|
||||
|
||||
Columns columns = Columns.from(returnedType.getInputProperties().toArray(new String[0]));
|
||||
query = query.columns(columns);
|
||||
}
|
||||
|
||||
RegularStatement statement = statementFactory.select(query, requirePersistentEntity());
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
@@ -144,8 +154,7 @@ class QueryStatementCreator {
|
||||
<T> T doWithQuery(CassandraParameterAccessor parameterAccessor, PartTree tree,
|
||||
Function<Query, ? extends T> function) {
|
||||
|
||||
CassandraQueryCreator queryCreator =
|
||||
new CassandraQueryCreator(tree, parameterAccessor, this.mappingContext);
|
||||
CassandraQueryCreator queryCreator = new CassandraQueryCreator(tree, parameterAccessor, this.mappingContext);
|
||||
|
||||
Query query = queryCreator.createQuery();
|
||||
|
||||
@@ -164,9 +173,8 @@ class QueryStatementCreator {
|
||||
if (queryOptions.isPresent()) {
|
||||
query = Optional.ofNullable(parameterAccessor.getQueryOptions()).map(query::queryOptions).orElse(query);
|
||||
} else if (this.queryMethod.hasConsistencyLevel()) {
|
||||
query = query.queryOptions(QueryOptions.builder()
|
||||
.consistencyLevel(this.queryMethod.getRequiredAnnotatedConsistencyLevel())
|
||||
.build());
|
||||
query = query.queryOptions(
|
||||
QueryOptions.builder().consistencyLevel(this.queryMethod.getRequiredAnnotatedConsistencyLevel()).build());
|
||||
}
|
||||
|
||||
return function.apply(query);
|
||||
@@ -178,8 +186,7 @@ class QueryStatementCreator {
|
||||
private boolean allowsFiltering() {
|
||||
|
||||
return this.queryMethod.getQueryAnnotation()
|
||||
.map(org.springframework.data.cassandra.repository.Query::allowFiltering)
|
||||
.orElse(false);
|
||||
.map(org.springframework.data.cassandra.repository.Query::allowFiltering).orElse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,8 +208,7 @@ class QueryStatementCreator {
|
||||
|
||||
if (queryOptions.isPresent()) {
|
||||
queryToUse = Optional.ofNullable(parameterAccessor.getQueryOptions())
|
||||
.map(it -> QueryOptionsUtil.addQueryOptions(boundQuery, it))
|
||||
.orElse(boundQuery);
|
||||
.map(it -> QueryOptionsUtil.addQueryOptions(boundQuery, it)).orElse(boundQuery);
|
||||
} else if (this.queryMethod.hasConsistencyLevel()) {
|
||||
queryToUse.setConsistencyLevel(this.queryMethod.getRequiredAnnotatedConsistencyLevel());
|
||||
}
|
||||
|
||||
@@ -104,7 +104,8 @@ public class ReactivePartTreeCassandraQuery extends AbstractReactiveCassandraQue
|
||||
return getQueryStatementCreator().exists(getStatementFactory(), getTree(), parameterAccessor);
|
||||
}
|
||||
|
||||
return getQueryStatementCreator().select(getStatementFactory(), getTree(), parameterAccessor);
|
||||
return getQueryStatementCreator().select(getStatementFactory(), getTree(), parameterAccessor,
|
||||
getQueryMethod().getResultProcessor());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -152,6 +150,24 @@ public class CassandraTemplateUnitTests {
|
||||
assertThat(statementCaptor.getValue().toString()).isEqualTo("SELECT * FROM users WHERE id='myid';");
|
||||
}
|
||||
|
||||
@Test // DATACASS-313
|
||||
public void selectProjectedOneShouldReturnMappedResults() {
|
||||
|
||||
when(resultSet.iterator()).thenReturn(Collections.singleton(row).iterator());
|
||||
when(columnDefinitions.contains(anyString())).thenReturn(true);
|
||||
when(columnDefinitions.getType(anyInt())).thenReturn(DataType.ascii());
|
||||
|
||||
when(columnDefinitions.getIndexOf("firstname")).thenReturn(0);
|
||||
|
||||
when(row.getObject(0)).thenReturn("Walter");
|
||||
|
||||
UserProjection user = template.query(User.class).as(UserProjection.class).oneValue();
|
||||
|
||||
assertThat(user.getFirstname()).isEqualTo("Walter");
|
||||
verify(session).execute(statementCaptor.capture());
|
||||
assertThat(statementCaptor.getValue().toString()).isEqualTo("SELECT firstname FROM users LIMIT 2;");
|
||||
}
|
||||
|
||||
@Test // DATACASS-292
|
||||
public void existsShouldReturnExistingElement() {
|
||||
|
||||
@@ -394,4 +410,8 @@ public class CassandraTemplateUnitTests {
|
||||
|
||||
verify(session).execute(Mockito.any(Batch.class));
|
||||
}
|
||||
|
||||
interface UserProjection {
|
||||
String getFirstname();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,20 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collections;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -36,7 +32,6 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.data.cassandra.ReactiveResultSet;
|
||||
import org.springframework.data.cassandra.ReactiveSession;
|
||||
import org.springframework.data.cassandra.core.query.Query;
|
||||
@@ -131,6 +126,28 @@ public class ReactiveCassandraTemplateUnitTests {
|
||||
assertThat(statementCaptor.getValue().toString()).isEqualTo("SELECT * FROM users WHERE id='myid';");
|
||||
}
|
||||
|
||||
@Test // DATACASS-313
|
||||
public void selectProjectedOneShouldReturnMappedResults() {
|
||||
|
||||
when(reactiveResultSet.rows()).thenReturn(Flux.just(row));
|
||||
when(columnDefinitions.contains(anyString())).thenReturn(true);
|
||||
when(columnDefinitions.getType(anyInt())).thenReturn(DataType.ascii());
|
||||
|
||||
when(columnDefinitions.getIndexOf("firstname")).thenReturn(0);
|
||||
|
||||
when(row.getObject(0)).thenReturn("Walter");
|
||||
|
||||
template.query(User.class).as(UserProjection.class).first() //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(actual -> {
|
||||
|
||||
assertThat(actual.getFirstname()).isEqualTo("Walter");
|
||||
}).verifyComplete();
|
||||
|
||||
verify(session).execute(statementCaptor.capture());
|
||||
assertThat(statementCaptor.getValue().toString()).isEqualTo("SELECT firstname FROM users LIMIT 1;");
|
||||
}
|
||||
|
||||
@Test // DATACASS-335
|
||||
public void existsShouldReturnExistingElement() {
|
||||
|
||||
@@ -266,4 +283,8 @@ public class ReactiveCassandraTemplateUnitTests {
|
||||
verify(session).execute(statementCaptor.capture());
|
||||
assertThat(statementCaptor.getValue().toString()).isEqualTo("TRUNCATE users;");
|
||||
}
|
||||
|
||||
interface UserProjection {
|
||||
String getFirstname();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
@@ -30,7 +30,6 @@ import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.cassandra.core.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
|
||||
@@ -118,20 +117,20 @@ public class PartTreeCassandraQueryUnitTests {
|
||||
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname='foo' AND lastname='bar';");
|
||||
}
|
||||
|
||||
@Test // DATACASS-7
|
||||
@Test // DATACASS-7, DATACASS-313
|
||||
public void usesDynamicProjection() {
|
||||
|
||||
String query = deriveQueryFromMethod("findDynamicallyProjectedBy", PersonProjection.class);
|
||||
|
||||
assertThat(query).isEqualTo("SELECT * FROM person;");
|
||||
assertThat(query).isEqualTo("SELECT lastname,firstname FROM person;");
|
||||
}
|
||||
|
||||
@Test // DATACASS-479
|
||||
@Test // DATACASS-479, DATACASS-313
|
||||
public void usesProjectionQueryHiddenField() {
|
||||
|
||||
String query = deriveQueryFromMethod("findPersonProjectedByNickname", "foo");
|
||||
|
||||
assertThat(query).isEqualTo("SELECT * FROM person WHERE nickname='foo';");
|
||||
assertThat(query).isEqualTo("SELECT lastname,firstname FROM person WHERE nickname='foo';");
|
||||
}
|
||||
|
||||
@Test // DATACASS-357
|
||||
|
||||
@@ -15,14 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import rx.Single;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -31,7 +32,6 @@ import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.data.cassandra.core.ReactiveCassandraOperations;
|
||||
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
|
||||
import org.springframework.data.cassandra.core.cql.QueryOptions;
|
||||
@@ -49,8 +49,6 @@ import org.springframework.util.ClassUtils;
|
||||
import com.datastax.driver.core.ConsistencyLevel;
|
||||
import com.datastax.driver.core.Statement;
|
||||
|
||||
import rx.Single;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ReactivePartTreeCassandraQuery}.
|
||||
*
|
||||
@@ -107,12 +105,12 @@ public class ReactivePartTreeCassandraQueryUnitTests {
|
||||
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname='foo' ALLOW FILTERING;");
|
||||
}
|
||||
|
||||
@Test // DATACASS-335
|
||||
@Test // DATACASS-335, DATACASS-313
|
||||
public void usesDynamicProjection() {
|
||||
|
||||
String query = deriveQueryFromMethod("findDynamicallyProjectedBy", PersonProjection.class);
|
||||
|
||||
assertThat(query).isEqualTo("SELECT * FROM person;");
|
||||
assertThat(query).isEqualTo("SELECT lastname,firstname FROM person;");
|
||||
}
|
||||
|
||||
@Test // DATACASS-146
|
||||
|
||||
Reference in New Issue
Block a user