DATACASS-512 - Polish.

Resolves #PR-118.
This commit is contained in:
John Blum
2018-01-23 17:07:46 -08:00
parent c0b9479599
commit c00e3f6b29
33 changed files with 368 additions and 257 deletions

View File

@@ -223,19 +223,22 @@ public interface AsyncCassandraOperations {
/**
* Returns the number of rows for the given entity class.
*
* @param entityClass must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return the number of existing entities.
* @throws DataAccessException if there is any problem executing the query.
* @throws DataAccessException if any problem occurs while executing the query.
*/
ListenableFuture<Long> count(Class<?> entityClass) throws DataAccessException;
/**
* Returns the number of rows for the given entity class applying {@link Query}.
*
* @param query must not be {@literal null}.
* @param entityClass must not be {@literal null}.
* This overridden method allows users to further refine the selection criteria using a {@link Query} predicate
* to determine how many entities of the given {@link Class type} match the criteria.
*
* @param query user-provided count {@link Query} to execute; must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return the number of existing entities.
* @throws DataAccessException if there is any problem executing the query.
* @throws DataAccessException if any problem occurs while executing the query.
* @since 2.1
*/
ListenableFuture<Long> count(Query query, Class<?> entityClass) throws DataAccessException;
@@ -243,22 +246,22 @@ public interface AsyncCassandraOperations {
/**
* Determine whether a row of {@code entityClass} with the given {@code id} exists.
*
* @param id the Id value. For single primary keys it's the plain value. For composite primary keys either the
* {@link org.springframework.data.cassandra.core.mapping.PrimaryKeyClass} or
* {@link org.springframework.data.cassandra.core.mapping.MapId}. Must not be {@literal null}.
* @param entityClass must not be {@literal null}.
* @return {@literal true}, if the object exists.
* @throws DataAccessException if there is any problem executing the query.
* @param id Id value. For single primary keys it's the plain value. For composite primary keys either, it's
* an instance of either {@link org.springframework.data.cassandra.core.mapping.PrimaryKeyClass}
* or {@link org.springframework.data.cassandra.core.mapping.MapId}. Must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return {@literal true} if the object exists.
* @throws DataAccessException if any problem occurs while executing the query.
*/
ListenableFuture<Boolean> exists(Object id, Class<?> entityClass) throws DataAccessException;
/**
* Determine whether the result for {@code entityClass} {@link Query} yields at least one row.
*
* @param query must not be {@literal null}.
* @param entityClass The entity type must not be {@literal null}.
* @return true, if the object exists.
* @throws DataAccessException if there is any problem executing the query.
* @param query user-provided exists {@link Query} to execute; must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return {@literal true} if the object exists.
* @throws DataAccessException if any problem occurs while executing the query.
* @since 2.1
*/
ListenableFuture<Boolean> exists(Query query, Class<?> entityClass) throws DataAccessException;

View File

@@ -178,16 +178,24 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
}
/**
* Returns the {@link CassandraMappingContext} used by this template to access mapping meta-data used to store (map)
* objects to Cassandra tables.
* Returns the {@link CassandraMappingContext} used by this template to access mapping meta-data
* in order to store (map) objects to Cassandra tables.
*
* @return the {@link CassandraMappingContext} used by this template.
* @see CassandraMappingContext
* @see org.springframework.data.cassandra.core.mapping.CassandraMappingContext
*/
protected MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> getMappingContext() {
return this.mappingContext;
}
private CassandraPersistentEntity<?> getRequiredPersistentEntity(Object entity) {
return getRequiredPersistentEntity(entity.getClass());
}
private CassandraPersistentEntity<?> getRequiredPersistentEntity(Class<?> entityType) {
return getMappingContext().getRequiredPersistentEntity(ClassUtils.getUserClass(entityType));
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
@@ -199,7 +207,11 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
}
private CqlIdentifier getTableName(Object entity) {
return getMappingContext().getRequiredPersistentEntity(ClassUtils.getUserClass(entity)).getTableName();
return getRequiredPersistentEntity(entity).getTableName();
}
private CqlIdentifier getTableName(Class<?> entityType) {
return getRequiredPersistentEntity(entityType).getTableName();
}
// -------------------------------------------------------------------------
@@ -400,8 +412,7 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
Assert.notNull(entityClass, "Entity type must not be null");
Select select = QueryBuilder.select().countAll()
.from(getMappingContext().getRequiredPersistentEntity(entityClass).getTableName().toCql());
Select select = QueryBuilder.select().countAll().from(getTableName(entityClass).toCql());
return getAsyncCqlOperations().queryForObject(select, Long.class);
}
@@ -415,8 +426,7 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
Assert.notNull(query, "Query must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
RegularStatement count = statementFactory.count(query,
getMappingContext().getRequiredPersistentEntity(entityClass));
RegularStatement count = getStatementFactory().count(query, getRequiredPersistentEntity(entityClass));
ListenableFuture<Long> result = getAsyncCqlOperations().queryForObject(count, Long.class);
@@ -432,7 +442,7 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
CassandraPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(entityClass);
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
Select select = QueryBuilder.select().from(entity.getTableName().toCql());
@@ -451,8 +461,8 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
Assert.notNull(query, "Query must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
RegularStatement select = statementFactory.select(query.limit(1),
getMappingContext().getRequiredPersistentEntity(entityClass));
RegularStatement select = getStatementFactory()
.select(query.limit(1), getRequiredPersistentEntity(entityClass));
return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().queryForResultSet(select),
resultSet -> resultSet.iterator().hasNext());
@@ -467,7 +477,7 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
CassandraPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(entityClass);
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
Select select = QueryBuilder.select().all().from(entity.getTableName().toCql());
@@ -495,8 +505,8 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
Insert insert = QueryUtils.createInsertQuery(getTableName(entity).toCql(), entity, options, getConverter());
return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().execute(new AsyncStatementCallback(insert)),
WriteResult::of);
return new MappingListenableFutureAdapter<>(
getAsyncCqlOperations().execute(new AsyncStatementCallback(insert)), WriteResult::of);
}
/* (non-Javadoc)
@@ -518,8 +528,8 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
Update update = QueryUtils.createUpdateQuery(getTableName(entity).toCql(), entity, options, getConverter());
return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().execute(new AsyncStatementCallback(update)),
WriteResult::of);
return new MappingListenableFutureAdapter<>(
getAsyncCqlOperations().execute(new AsyncStatementCallback(update)), WriteResult::of);
}
/* (non-Javadoc)
@@ -541,8 +551,8 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
Delete delete = QueryUtils.createDeleteQuery(getTableName(entity).toCql(), entity, options, getConverter());
return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().execute(new AsyncStatementCallback(delete)),
WriteResult::of);
return new MappingListenableFutureAdapter<>(getAsyncCqlOperations()
.execute(new AsyncStatementCallback(delete)), WriteResult::of);
}
/* (non-Javadoc)
@@ -554,7 +564,7 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
CassandraPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(entityClass);
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
Delete delete = QueryBuilder.delete().from(entity.getTableName().toCql());
@@ -571,8 +581,7 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
Assert.notNull(entityClass, "Entity type must not be null");
Truncate truncate = QueryBuilder
.truncate(getMappingContext().getRequiredPersistentEntity(entityClass).getTableName().toCql());
Truncate truncate = QueryBuilder.truncate(getTableName(entityClass).toCql());
return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().execute(truncate), aBoolean -> null);
}
@@ -581,6 +590,10 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
// Implementation hooks and helper methods
// -------------------------------------------------------------------------
private int getConfiguredFetchSize(Session session) {
return session.getCluster().getConfiguration().getQueryOptions().getFetchSize();
}
@SuppressWarnings("ConstantConditions")
private int getEffectiveFetchSize(Statement statement) {
@@ -589,14 +602,16 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations {
}
if (getAsyncCqlOperations() instanceof CassandraAccessor) {
CassandraAccessor accessor = (CassandraAccessor) getAsyncCqlOperations();
if (accessor.getFetchSize() != -1) {
return accessor.getFetchSize();
}
}
return getAsyncCqlOperations().execute((AsyncSessionCallback<Integer>) session -> AsyncResult
.forValue(session.getCluster().getConfiguration().getQueryOptions().getFetchSize())).completable().join();
return getAsyncCqlOperations().execute((AsyncSessionCallback<Integer>) session ->
AsyncResult.forValue(getConfiguredFetchSize(session))).completable().join();
}
static class MappingListenableFutureAdapter<T, S>

View File

@@ -250,19 +250,22 @@ public interface CassandraOperations {
/**
* Returns the number of rows for the given entity class.
*
* @param entityClass must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return the number of existing entities.
* @throws DataAccessException if there is any problem executing the query.
* @throws DataAccessException if any problem occurs while executing the query.
*/
long count(Class<?> entityClass) throws DataAccessException;
/**
* Returns the number of rows for the given entity class applying {@link Query}.
*
* @param query must not be {@literal null}.
* @param entityClass must not be {@literal null}.
* This overridden method allows users to further refine the selection criteria using a {@link Query} predicate
* to determine how many entities of the given {@link Class type} match the criteria.
*
* @param query user-defined count {@link Query} to execute; must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return the number of existing entities.
* @throws DataAccessException if there is any problem executing the query.
* @throws DataAccessException if any problem occurs while executing the query.
* @since 2.1
*/
long count(Query query, Class<?> entityClass) throws DataAccessException;
@@ -270,22 +273,22 @@ public interface CassandraOperations {
/**
* Determine whether a row of {@code entityClass} with the given {@code id} exists.
*
* @param id the Id value. For single primary keys it's the plain value. For composite primary keys either the
* {@link org.springframework.data.cassandra.core.mapping.PrimaryKeyClass} or
* {@link org.springframework.data.cassandra.core.mapping.MapId}. Must not be {@literal null}.
* @param entityClass The entity type must not be {@literal null}.
* @return true, if the object exists.
* @throws DataAccessException if there is any problem executing the query.
* @param id Id value. For single primary keys it's the plain value. For composite primary keys either, it's
* an instance of either {@link org.springframework.data.cassandra.core.mapping.PrimaryKeyClass}
* or {@link org.springframework.data.cassandra.core.mapping.MapId}. Must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return {@literal true} if the object exists.
* @throws DataAccessException if any problem occurs while executing the query.
*/
boolean exists(Object id, Class<?> entityClass) throws DataAccessException;
/**
* Determine whether the result for {@code entityClass} {@link Query} yields at least one row.
*
* @param query must not be {@literal null}.
* @param entityClass The entity type must not be {@literal null}.
* @return true, if the object exists.
* @throws DataAccessException if there is any problem executing the query.
* @param query user-defined exists {@link Query} to execute; must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return {@literal true} if the object exists.
* @throws DataAccessException if any problem occurs while executing the query.
* @since 2.1
*/
boolean exists(Query query, Class<?> entityClass) throws DataAccessException;

View File

@@ -15,13 +15,13 @@
*/
package org.springframework.data.cassandra.core;
import lombok.NonNull;
import lombok.Value;
import java.util.List;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import lombok.NonNull;
import lombok.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.data.cassandra.SessionFactory;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
@@ -172,16 +172,24 @@ public class CassandraTemplate implements CassandraOperations {
}
/**
* Returns the {@link CassandraMappingContext} used by this template to access mapping meta-data used to store (map)
* object to Cassandra tables.
* Returns the {@link CassandraMappingContext} used by this template to access mapping meta-data
* in order to store (map) object to Cassandra tables.
*
* @return the {@link CassandraMappingContext} used by this template.
* @see CassandraMappingContext
* @see org.springframework.data.cassandra.core.mapping.CassandraMappingContext
*/
protected MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> getMappingContext() {
return this.mappingContext;
}
private CassandraPersistentEntity<?> getRequiredPersistentEntity(Object entity) {
return getRequiredPersistentEntity(entity.getClass());
}
private CassandraPersistentEntity<?> getRequiredPersistentEntity(Class<?> entityType) {
return getMappingContext().getRequiredPersistentEntity(ClassUtils.getUserClass(entityType));
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
@@ -192,6 +200,18 @@ public class CassandraTemplate implements CassandraOperations {
return this.statementFactory;
}
private CqlIdentifier getTableName(Object entity) {
return getRequiredPersistentEntity(entity).getTableName();
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraOperations#getTableName(java.lang.Class)
*/
@Override
public CqlIdentifier getTableName(Class<?> entityClass) {
return getRequiredPersistentEntity(entityClass).getTableName();
}
// -------------------------------------------------------------------------
// Methods dealing with static CQL
// -------------------------------------------------------------------------
@@ -379,8 +399,7 @@ public class CassandraTemplate implements CassandraOperations {
Assert.notNull(entityClass, "Entity type must not be null");
Select select = QueryBuilder.select().countAll()
.from(getMappingContext().getRequiredPersistentEntity(entityClass).getTableName().toCql());
Select select = QueryBuilder.select().countAll().from(getTableName(entityClass).toCql());
Long count = getCqlOperations().queryForObject(select, Long.class);
@@ -396,8 +415,7 @@ public class CassandraTemplate implements CassandraOperations {
Assert.notNull(query, "Query must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
RegularStatement count = statementFactory.count(query,
getMappingContext().getRequiredPersistentEntity(entityClass));
RegularStatement count = getStatementFactory().count(query, getRequiredPersistentEntity(entityClass));
Long result = getCqlOperations().queryForObject(count, Long.class);
@@ -413,7 +431,7 @@ public class CassandraTemplate implements CassandraOperations {
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
CassandraPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(entityClass);
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
Select select = QueryBuilder.select().from(entity.getTableName().toCql());
@@ -431,8 +449,8 @@ public class CassandraTemplate implements CassandraOperations {
Assert.notNull(query, "Query must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
RegularStatement select = statementFactory.select(query.limit(1),
getMappingContext().getRequiredPersistentEntity(entityClass));
RegularStatement select = getStatementFactory()
.select(query.limit(1), getRequiredPersistentEntity(entityClass));
return getCqlOperations().queryForResultSet(select).iterator().hasNext();
}
@@ -446,7 +464,7 @@ public class CassandraTemplate implements CassandraOperations {
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
CassandraPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(entityClass);
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
Select select = QueryBuilder.select().all().from(entity.getTableName().toCql());
@@ -472,7 +490,7 @@ public class CassandraTemplate implements CassandraOperations {
Assert.notNull(entity, "Entity must not be null");
Assert.notNull(options, "InsertOptions must not be null");
Insert insert = QueryUtils.createInsertQuery(getTableName(entity.getClass()).toCql(), entity, options, converter);
Insert insert = QueryUtils.createInsertQuery(getTableName(entity).toCql(), entity, options, getConverter());
// noinspection ConstantConditions
return getCqlOperations().execute(new StatementCallback(insert));
@@ -495,7 +513,7 @@ public class CassandraTemplate implements CassandraOperations {
Assert.notNull(entity, "Entity must not be null");
Assert.notNull(options, "UpdateOptions must not be null");
Update update = QueryUtils.createUpdateQuery(getTableName(entity.getClass()).toCql(), entity, options, converter);
Update update = QueryUtils.createUpdateQuery(getTableName(entity).toCql(), entity, options, getConverter());
// noinspection ConstantConditions
return getCqlOperations().execute(new StatementCallback(update));
@@ -518,7 +536,7 @@ public class CassandraTemplate implements CassandraOperations {
Assert.notNull(entity, "Entity must not be null");
Assert.notNull(options, "QueryOptions must not be null");
Delete delete = QueryUtils.createDeleteQuery(getTableName(entity.getClass()).toCql(), entity, options, converter);
Delete delete = QueryUtils.createDeleteQuery(getTableName(entity).toCql(), entity, options, getConverter());
// noinspection ConstantConditions
return getCqlOperations().execute(new StatementCallback(delete));
@@ -533,7 +551,7 @@ public class CassandraTemplate implements CassandraOperations {
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
CassandraPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(entityClass);
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
Delete delete = QueryBuilder.delete().from(entity.getTableName().toCql());
@@ -550,8 +568,7 @@ public class CassandraTemplate implements CassandraOperations {
Assert.notNull(entityClass, "Entity type must not be null");
Truncate truncate = QueryBuilder
.truncate(getMappingContext().getRequiredPersistentEntity(entityClass).getTableName().toCql());
Truncate truncate = QueryBuilder.truncate(getTableName(entityClass).toCql());
getCqlOperations().execute(truncate);
}
@@ -560,12 +577,8 @@ public class CassandraTemplate implements CassandraOperations {
// Implementation hooks and helper methods
// -------------------------------------------------------------------------
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraOperations#getTableName(java.lang.Class)
*/
@Override
public CqlIdentifier getTableName(Class<?> entityClass) {
return getMappingContext().getRequiredPersistentEntity(ClassUtils.getUserClass(entityClass)).getTableName();
private int getConfiguredFetchSize(Session session) {
return session.getCluster().getConfiguration().getQueryOptions().getFetchSize();
}
@SuppressWarnings("ConstantConditions")
@@ -576,14 +589,15 @@ public class CassandraTemplate implements CassandraOperations {
}
if (getCqlOperations() instanceof CassandraAccessor) {
CassandraAccessor accessor = (CassandraAccessor) getCqlOperations();
if (accessor.getFetchSize() != -1) {
return accessor.getFetchSize();
}
}
return getCqlOperations().execute(
(SessionCallback<Integer>) session -> session.getCluster().getConfiguration().getQueryOptions().getFetchSize());
return getCqlOperations().execute(this::getConfiguredFetchSize);
}
/* (non-Javadoc)

View File

@@ -158,19 +158,22 @@ public interface ReactiveCassandraOperations {
/**
* Returns the number of rows for the given entity class.
*
* @param entityClass must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return the number of existing entities.
* @throws DataAccessException if there is any problem issuing the execution.
* @throws DataAccessException if any problem occurs while executing the query.
*/
Mono<Long> count(Class<?> entityClass) throws DataAccessException;
/**
* Returns the number of rows for the given entity class applying {@link Query}.
*
* @param query must not be {@literal null}.
* @param entityClass must not be {@literal null}.
* This overridden method allows users to further refine the selection criteria using a {@link Query} predicate
* to determine how many entities of the given {@link Class type} match the criteria.
*
* @param query user-defined count {@link Query} to execute; must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return the number of existing entities.
* @throws DataAccessException if there is any problem executing the query.
* @throws DataAccessException if any problem occurs while executing the query.
* @since 2.1
*/
Mono<Long> count(Query query, Class<?> entityClass) throws DataAccessException;
@@ -178,22 +181,22 @@ public interface ReactiveCassandraOperations {
/**
* Determine whether a row of {@code entityClass} with the given {@code id} exists.
*
* @param id the Id value. For single primary keys it's the plain value. For composite primary keys either the
* {@link org.springframework.data.cassandra.core.mapping.PrimaryKeyClass} or
* {@link org.springframework.data.cassandra.core.mapping.MapId}. Must not be {@literal null}.
* @param entityClass must not be {@literal null}.
* @param id Id value. For single primary keys it's the plain value. For composite primary keys either, it's
* an instance of either {@link org.springframework.data.cassandra.core.mapping.PrimaryKeyClass}
* or {@link org.springframework.data.cassandra.core.mapping.MapId}. Must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return {@literal true} if the object exists.
* @throws DataAccessException if there is any problem issuing the execution.
* @throws DataAccessException if any problem occurs while executing the query.
*/
Mono<Boolean> exists(Object id, Class<?> entityClass) throws DataAccessException;
/**
* Determine whether the result for {@code entityClass} {@link Query} yields at least one row.
*
* @param query must not be {@literal null}.
* @param entityClass The entity type must not be {@literal null}.
* @return true, if the object exists.
* @throws DataAccessException if there is any problem executing the query.
* @param query user-defined exists {@link Query} to execute; must not be {@literal null}.
* @param entityClass {@link Class type} of the entity; must not be {@literal null}.
* @return {@literal true} if the object exists.
* @throws DataAccessException if any problem occurs while executing the query.
* @since 2.1
*/
Mono<Boolean> exists(Query query, Class<?> entityClass) throws DataAccessException;

View File

@@ -17,6 +17,7 @@ package org.springframework.data.cassandra.core;
import lombok.NonNull;
import lombok.Value;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -189,6 +190,14 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations {
return this.cqlOperations;
}
private CassandraPersistentEntity<?> getRequiredPersistentEntity(Object entity) {
return getRequiredPersistentEntity(entity.getClass());
}
private CassandraPersistentEntity<?> getRequiredPersistentEntity(Class<?> entityType) {
return getMappingContext().getRequiredPersistentEntity(ClassUtils.getUserClass(entityType));
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
@@ -199,9 +208,12 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations {
return this.statementFactory;
}
/* (non-Javadoc) */
private CqlIdentifier getTableName(Object entity) {
return getMappingContext().getRequiredPersistentEntity(ClassUtils.getUserClass(entity)).getTableName();
return getRequiredPersistentEntity(entity).getTableName();
}
private CqlIdentifier getTableName(Class<?> entityType) {
return getRequiredPersistentEntity(entityType).getTableName();
}
// -------------------------------------------------------------------------
@@ -322,8 +334,7 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations {
Assert.notNull(entityClass, "Entity type must not be null");
Select select = QueryBuilder.select().countAll()
.from(getMappingContext().getRequiredPersistentEntity(entityClass).getTableName().toCql());
Select select = QueryBuilder.select().countAll().from(getTableName(entityClass).toCql());
return getReactiveCqlOperations().queryForObject(select, Long.class);
}
@@ -337,8 +348,7 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations {
Assert.notNull(query, "Query must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
RegularStatement count = statementFactory.count(query,
getMappingContext().getRequiredPersistentEntity(entityClass));
RegularStatement count = getStatementFactory().count(query, getRequiredPersistentEntity(entityClass));
return getReactiveCqlOperations().queryForObject(count, Long.class);
}
@@ -352,7 +362,7 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations {
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
CassandraPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(entityClass);
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
Select select = QueryBuilder.select().from(entity.getTableName().toCql());
@@ -370,8 +380,8 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations {
Assert.notNull(query, "Query must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
RegularStatement select = statementFactory.select(query.limit(1),
getMappingContext().getRequiredPersistentEntity(entityClass));
RegularStatement select = getStatementFactory()
.select(query.limit(1), getRequiredPersistentEntity(entityClass));
return getReactiveCqlOperations().queryForRows(select).hasElements();
}
@@ -385,7 +395,7 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations {
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
CassandraPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(entityClass);
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
Select select = QueryBuilder.select().all().from(entity.getTableName().toCql());
@@ -433,7 +443,7 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations {
Assert.notNull(entity, "Entity must not be null");
Assert.notNull(options, "UpdateOptions must not be null");
Update update = QueryUtils.createUpdateQuery(getTableName(entity).toCql(), entity, options, converter);
Update update = QueryUtils.createUpdateQuery(getTableName(entity).toCql(), entity, options, getConverter());
return getReactiveCqlOperations().execute(new StatementCallback(update)).next();
}
@@ -469,7 +479,7 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations {
Assert.notNull(id, "Id must not be null");
Assert.notNull(entityClass, "Entity type must not be null");
CassandraPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(entityClass);
CassandraPersistentEntity<?> entity = getRequiredPersistentEntity(entityClass);
Delete delete = QueryBuilder.delete().from(entity.getTableName().toCql());
@@ -486,8 +496,7 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations {
Assert.notNull(entityClass, "Entity type must not be null");
Truncate truncate = QueryBuilder
.truncate(getMappingContext().getRequiredPersistentEntity(entityClass).getTableName().toCql());
Truncate truncate = QueryBuilder.truncate(getTableName(entityClass).toCql());
return getReactiveCqlOperations().execute(truncate).then();
}

View File

@@ -125,6 +125,26 @@ public class StatementFactory {
return this.updateMapper;
}
/**
* Create a {@literal COUNT} statement by mapping {@link Query} to {@link Select}.
*
* @param query user-defined count {@link Query} to execute; must not be {@literal null}.
* @param entity {@link CassandraPersistentEntity entity} to count; must not be {@literal null}.
* @return the rendered {@link RegularStatement}.
* @since 2.1
*/
public RegularStatement count(Query query, CassandraPersistentEntity<?> entity) {
Assert.notNull(query, "Query must not be null");
Assert.notNull(entity, "Entity must not be null");
Filter filter = getQueryMapper().getMappedObject(query, entity);
List<Selector> selectors = Collections.singletonList(FunctionCall.from("COUNT", 1L));
return createSelect(query, entity, filter, selectors);
}
/**
* Create a {@literal SELECT} statement by mapping {@link Query} to {@link Select}.
*
@@ -144,26 +164,6 @@ public class StatementFactory {
return createSelect(query, entity, filter, selectors);
}
/**
* Create a {@literal COUNT} statement by mapping {@link Query} to {@link Select}.
*
* @param query must not be {@literal null}.
* @param entity must not be {@literal null}.
* @return the rendered {@link RegularStatement}.
* @since 2.1
*/
public RegularStatement count(Query query, CassandraPersistentEntity<?> entity) {
Assert.notNull(query, "Query must not be null");
Assert.notNull(entity, "Entity must not be null");
Filter filter = getQueryMapper().getMappedObject(query, entity);
List<Selector> selectors = Collections.singletonList(FunctionCall.from("COUNT", 1L));
return createSelect(query, entity, filter, selectors);
}
private Select createSelect(Query query, CassandraPersistentEntity<?> entity, Filter filter,
List<Selector> selectors) {
@@ -194,10 +194,11 @@ public class StatementFactory {
if (selectors.isEmpty()) {
select = QueryBuilder.select().all().from(from.toCql());
} else {
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());
}
@@ -206,6 +207,7 @@ public class StatementFactory {
}
if (sort.isSorted()) {
List<Ordering> orderings = new ArrayList<>();
for (Order order : sort) {
@@ -459,7 +461,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()));
}
}

View File

@@ -30,8 +30,8 @@ import org.springframework.core.annotation.AliasFor;
* @author Mark Paluch
* @since 2.1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Query(count = true)
public @interface CountQuery {
@@ -42,4 +42,5 @@ public @interface CountQuery {
*/
@AliasFor(annotation = Query.class)
String value() default "";
}

View File

@@ -30,8 +30,8 @@ import org.springframework.core.annotation.AliasFor;
* @author Mark Paluch
* @since 2.1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Query(exists = true)
public @interface ExistsQuery {
@@ -42,4 +42,5 @@ public @interface ExistsQuery {
*/
@AliasFor(annotation = Query.class)
String value() default "";
}

View File

@@ -50,16 +50,17 @@ public @interface Query {
boolean allowFiltering() default false;
/**
* Returns whether the query defined should be executed as count projection.
* Returns whether the defined query should be executed as a count projection.
*
* @since 2.1
*/
boolean count() default false;
/**
* Returns whether the query defined should be executed as exists projection.
* Returns whether the defined query should be executed as an exists projection.
*
* @since 2.1
*/
boolean exists() default false;
}

View File

@@ -17,6 +17,8 @@ package org.springframework.data.cassandra.repository.query;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.repository.query.CassandraQueryExecution.CollectionExecution;
import org.springframework.data.cassandra.repository.query.CassandraQueryExecution.ExistsExecution;
import org.springframework.data.cassandra.repository.query.CassandraQueryExecution.ResultProcessingConverter;
@@ -44,6 +46,17 @@ public abstract class AbstractCassandraQuery extends CassandraRepositoryQuerySup
private final CassandraOperations operations;
private static CassandraConverter toConverter(CassandraOperations operations) {
Assert.notNull(operations, "CassandraOperations must not be null");
return operations.getConverter();
}
private static CassandraMappingContext toMappingContext(CassandraOperations operations) {
return toConverter(operations).getMappingContext();
}
/**
* Create a new {@link AbstractCassandraQuery} from the given {@link CassandraQueryMethod} and
* {@link CassandraOperations}.
@@ -53,13 +66,17 @@ public abstract class AbstractCassandraQuery extends CassandraRepositoryQuerySup
*/
public AbstractCassandraQuery(CassandraQueryMethod queryMethod, CassandraOperations operations) {
super(queryMethod, operations.getConverter().getMappingContext());
Assert.notNull(operations, "CassandraOperations must not be null");
super(queryMethod, toMappingContext(operations));
this.operations = operations;
}
/**
* Return a reference to the {@link CassandraOperations} used to execute this Cassandra query.
*
* @return a reference to the {@link CassandraOperations} used to execute this Cassandra query.
* @see org.springframework.data.cassandra.core.CassandraOperations
*/
protected CassandraOperations getOperations() {
return this.operations;
}
@@ -71,7 +88,7 @@ public abstract class AbstractCassandraQuery extends CassandraRepositoryQuerySup
@Override
public Object execute(Object[] parameters) {
CassandraParameterAccessor parameterAccessor = new ConvertingParameterAccessor(getOperations().getConverter(),
CassandraParameterAccessor parameterAccessor = new ConvertingParameterAccessor(toConverter(getOperations()),
new CassandraParametersParameterAccessor(getQueryMethod(), parameters));
ResultProcessor resultProcessor = getQueryMethod().getResultProcessor().withDynamicProjection(parameterAccessor);
@@ -79,7 +96,7 @@ public abstract class AbstractCassandraQuery extends CassandraRepositoryQuerySup
Statement statement = createQuery(parameterAccessor);
CassandraQueryExecution queryExecution = getExecution(parameterAccessor, new ResultProcessingConverter(
resultProcessor, getOperations().getConverter().getMappingContext(), getEntityInstantiators()));
resultProcessor, toMappingContext(getOperations()), getEntityInstantiators()));
Class<?> resultType = resolveResultType(resultProcessor);
@@ -91,7 +108,7 @@ public abstract class AbstractCassandraQuery extends CassandraRepositoryQuerySup
CassandraReturnedType returnedType = new CassandraReturnedType(resultProcessor.getReturnedType(),
getOperations().getConverter().getCustomConversions());
return (returnedType.isProjecting() ? returnedType.getDomainType() : returnedType.getReturnedType());
return returnedType.isProjecting() ? returnedType.getDomainType() : returnedType.getReturnedType();
}
/**
@@ -110,6 +127,7 @@ public abstract class AbstractCassandraQuery extends CassandraRepositoryQuerySup
*/
private CassandraQueryExecution getExecution(CassandraParameterAccessor parameterAccessor,
Converter<Object, Object> resultProcessing) {
return new ResultProcessingExecution(getExecutionToWrap(parameterAccessor, resultProcessing), resultProcessing);
}
@@ -136,7 +154,7 @@ public abstract class AbstractCassandraQuery extends CassandraRepositoryQuerySup
/**
* Returns whether the query should get a count projection applied.
*
* @return
* @return a boolean value indicating whether the query is a count projection.
* @since 2.1
*/
protected abstract boolean isCountQuery();
@@ -144,8 +162,9 @@ public abstract class AbstractCassandraQuery extends CassandraRepositoryQuerySup
/**
* Returns whether the query should get an exists projection applied.
*
* @return
* @return a boolean value indicating whether the query is an exists projection.
* @since 2.1
*/
protected abstract boolean isExistsQuery();
}

View File

@@ -22,6 +22,8 @@ import org.reactivestreams.Publisher;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.ReactiveCassandraOperations;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.repository.query.ReactiveCassandraQueryExecution.CollectionExecution;
import org.springframework.data.cassandra.repository.query.ReactiveCassandraQueryExecution.ExistsExecution;
import org.springframework.data.cassandra.repository.query.ReactiveCassandraQueryExecution.ResultProcessingConverter;
@@ -45,6 +47,17 @@ public abstract class AbstractReactiveCassandraQuery extends CassandraRepository
private final ReactiveCassandraOperations operations;
private static CassandraConverter toConverter(ReactiveCassandraOperations operations) {
Assert.notNull(operations, "ReactiveCassandraOperations must not be null");
return operations.getConverter();
}
private static CassandraMappingContext toMappingContext(ReactiveCassandraOperations operations) {
return toConverter(operations).getMappingContext();
}
/**
* Create a new {@link AbstractReactiveCassandraQuery} from the given {@link CassandraQueryMethod} and
* {@link CassandraOperations}.
@@ -54,9 +67,7 @@ public abstract class AbstractReactiveCassandraQuery extends CassandraRepository
*/
public AbstractReactiveCassandraQuery(ReactiveCassandraQueryMethod method, ReactiveCassandraOperations operations) {
super(method, operations.getConverter().getMappingContext());
Assert.notNull(operations, "ReactiveCassandraOperations must not be null");
super(method, toMappingContext(operations));
this.operations = operations;
}
@@ -80,22 +91,27 @@ public abstract class AbstractReactiveCassandraQuery extends CassandraRepository
*/
@Override
public Object execute(Object[] parameters) {
return (getQueryMethod().hasReactiveWrapperParameter() ? executeDeferred(parameters) : executeNow(parameters));
return getQueryMethod().hasReactiveWrapperParameter()
? executeDeferred(parameters)
: executeNow(parameters);
}
@SuppressWarnings("unchecked")
private Object executeDeferred(Object[] parameters) {
return (getQueryMethod().isCollectionQuery() ? Flux.defer(() -> (Publisher<Object>) execute(parameters))
: Mono.defer(() -> (Mono<Object>) execute(parameters)));
return getQueryMethod().isCollectionQuery()
? Flux.defer(() -> (Publisher<Object>) execute(parameters))
: Mono.defer(() -> (Mono<Object>) execute(parameters));
}
private Object executeNow(Object[] parameters) {
ReactiveCassandraParameterAccessor parameterAccessor =
new ReactiveCassandraParameterAccessor(getQueryMethod(), parameters);
new ReactiveCassandraParameterAccessor(getQueryMethod(), parameters);
CassandraParameterAccessor convertingParameterAccessor = new ConvertingParameterAccessor(
getReactiveCassandraOperations().getConverter(), parameterAccessor);
toConverter(getReactiveCassandraOperations()), parameterAccessor);
Statement statement = createQuery(convertingParameterAccessor);
@@ -103,7 +119,7 @@ public abstract class AbstractReactiveCassandraQuery extends CassandraRepository
.withDynamicProjection(convertingParameterAccessor);
ReactiveCassandraQueryExecution queryExecution = getExecution(new ResultProcessingConverter(resultProcessor,
getReactiveCassandraOperations().getConverter().getMappingContext(), getEntityInstantiators()));
toMappingContext(getReactiveCassandraOperations()), getEntityInstantiators()));
Class<?> resultType = resolveResultType(resultProcessor);
@@ -113,7 +129,7 @@ public abstract class AbstractReactiveCassandraQuery extends CassandraRepository
private Class<?> resolveResultType(ResultProcessor resultProcessor) {
CassandraReturnedType returnedType = new CassandraReturnedType(resultProcessor.getReturnedType(),
getReactiveCassandraOperations().getConverter().getCustomConversions());
toConverter(getReactiveCassandraOperations()).getCustomConversions());
return (returnedType.isProjecting() ? returnedType.getDomainType() : returnedType.getReturnedType());
}
@@ -139,8 +155,8 @@ public abstract class AbstractReactiveCassandraQuery extends CassandraRepository
if (getQueryMethod().isCollectionQuery()) {
return new CollectionExecution(getReactiveCassandraOperations());
} else if (isCountQuery()) {
return ((statement, type) -> new SingleEntityExecution(getReactiveCassandraOperations()).execute(statement,
Long.class));
return ((statement, type) ->
new SingleEntityExecution(getReactiveCassandraOperations()).execute(statement, Long.class));
} else if (isExistsQuery()) {
return new ExistsExecution(getReactiveCassandraOperations());
} else {
@@ -151,7 +167,7 @@ public abstract class AbstractReactiveCassandraQuery extends CassandraRepository
/**
* Returns whether the query should get a count projection applied.
*
* @return
* @return a boolean value indicating whether the query is a count projection.
* @since 2.1
*/
protected abstract boolean isCountQuery();
@@ -159,8 +175,9 @@ public abstract class AbstractReactiveCassandraQuery extends CassandraRepository
/**
* Returns whether the query should get an exists projection applied.
*
* @return
* @return a boolean value indicating whether the query is an exists projection.
* @since 2.1
*/
protected abstract boolean isExistsQuery();
}

View File

@@ -153,7 +153,7 @@ interface CassandraQueryExecution {
@Override
public Object execute(Statement statement, Class<?> type) {
ResultSet resultSet = operations.getCqlOperations().queryForResultSet(statement);
ResultSet resultSet = this.operations.getCqlOperations().queryForResultSet(statement);
Iterator<Row> iterator = resultSet.iterator();
@@ -161,9 +161,10 @@ interface CassandraQueryExecution {
Row row = iterator.next();
if (!iterator.hasNext() && ProjectionUtil.isCountProjection(row)) {
if (!iterator.hasNext() && ProjectionUtil.qualifiesAsCountProjection(row)) {
Object object = row.getObject(0);
return ((Number) object).longValue() > 0;
}

View File

@@ -60,12 +60,7 @@ public abstract class CassandraRepositoryQuerySupport implements RepositoryQuery
*/
@Deprecated
public CassandraRepositoryQuerySupport(CassandraQueryMethod queryMethod) {
Assert.notNull(queryMethod, "CassandraQueryMethod must not be null");
this.queryMethod = queryMethod;
this.instantiators = new EntityInstantiators();
this.queryStatementCreator = new QueryStatementCreator(queryMethod, new CassandraMappingContext());
this(queryMethod, new CassandraMappingContext());
}
/**
@@ -100,7 +95,7 @@ public abstract class CassandraRepositoryQuerySupport implements RepositoryQuery
}
protected QueryStatementCreator getQueryStatementCreator() {
return queryStatementCreator;
return this.queryStatementCreator;
}
@RequiredArgsConstructor

View File

@@ -112,7 +112,7 @@ public class PartTreeCassandraQuery extends AbstractCassandraQuery {
*/
@Override
protected boolean isCountQuery() {
return tree.isCountProjection();
return getTree().isCountProjection();
}
/* (non-Javadoc)
@@ -120,6 +120,6 @@ public class PartTreeCassandraQuery extends AbstractCassandraQuery {
*/
@Override
protected boolean isExistsQuery() {
return tree.isExistsProjection();
return getTree().isExistsProjection();
}
}

View File

@@ -15,12 +15,12 @@
*/
package org.springframework.data.cassandra.repository.query;
import lombok.experimental.UtilityClass;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import lombok.experimental.UtilityClass;
import com.datastax.driver.core.ColumnDefinitions;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.Row;
@@ -37,19 +37,6 @@ class ProjectionUtil {
private final static Set<DataType> NUMERIC_TYPES = new HashSet<>(Arrays.asList(DataType.bigint(), DataType.varint(),
DataType.smallint(), DataType.cint(), DataType.counter(), DataType.tinyint()));
/**
* Determine wether the {@link Row} qualifies for a count projection. Count projection candidates have a single
* numeric column.
*
* @param row
* @return
*/
static boolean isCountProjection(Row row) {
ColumnDefinitions columnDefinitions = row.getColumnDefinitions();
return columnDefinitions.size() == 1 && NUMERIC_TYPES.contains(columnDefinitions.getType(0));
}
/**
* Determine whether multiple {@code boolean} flags are set. Allowed is at most a single {@literal true} value.
*
@@ -59,4 +46,19 @@ class ProjectionUtil {
static boolean hasAmbiguousProjectionFlags(Boolean... flags) {
return Arrays.stream(flags).filter(Boolean::booleanValue).count() > 1;
}
/**
* Determine whether the {@link Row} qualifies as a count projection.
*
* Count projection candidates have a single numeric column.
*
* @param row {@link Row} to evaluate for a count projection.
* @return a boolean value indicating whether the {@link Row} qualifies as a count projection.
*/
static boolean qualifiesAsCountProjection(Row row) {
ColumnDefinitions columnDefinitions = row.getColumnDefinitions();
return columnDefinitions.size() == 1 && NUMERIC_TYPES.contains(columnDefinitions.getType(0));
}
}

View File

@@ -15,13 +15,11 @@
*/
package org.springframework.data.cassandra.repository.query;
import lombok.RequiredArgsConstructor;
import java.util.Optional;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.cassandra.core.StatementFactory;
import org.springframework.data.cassandra.core.cql.QueryOptions;
import org.springframework.data.cassandra.core.cql.QueryOptionsUtil;
@@ -32,6 +30,9 @@ import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.query.QueryCreationException;
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;
@@ -52,6 +53,10 @@ class QueryStatementCreator {
private final MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext;
private CassandraPersistentEntity<?> requirePersistentEntity() {
return this.mappingContext.getRequiredPersistentEntity(this.queryMethod.getDomainClass());
}
/**
* Create a {@literal SELECT} {@link Statement} from a {@link PartTree} and apply query options.
*
@@ -65,10 +70,7 @@ class QueryStatementCreator {
Function<Query, Statement> function = query -> {
CassandraPersistentEntity<?> persistentEntity = mappingContext
.getRequiredPersistentEntity(queryMethod.getDomainClass());
RegularStatement statement = statementFactory.select(query, persistentEntity);
RegularStatement statement = statementFactory.select(query, requirePersistentEntity());
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Created query [%s].", statement));
@@ -93,10 +95,7 @@ class QueryStatementCreator {
Function<Query, Statement> function = query -> {
CassandraPersistentEntity<?> persistentEntity = mappingContext
.getRequiredPersistentEntity(queryMethod.getDomainClass());
RegularStatement statement = statementFactory.count(query, persistentEntity);
RegularStatement statement = statementFactory.count(query, requirePersistentEntity());
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Created query [%s].", statement));
@@ -122,10 +121,7 @@ class QueryStatementCreator {
Function<Query, Statement> function = query -> {
CassandraPersistentEntity<?> persistentEntity = mappingContext
.getRequiredPersistentEntity(queryMethod.getDomainClass());
RegularStatement statement = statementFactory.select(query.limit(1), persistentEntity);
RegularStatement statement = statementFactory.select(query.limit(1), requirePersistentEntity());
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Created query [%s].", statement));
@@ -148,7 +144,8 @@ class QueryStatementCreator {
<T> T doWithQuery(CassandraParameterAccessor parameterAccessor, PartTree tree,
Function<Query, ? extends T> function) {
CassandraQueryCreator queryCreator = new CassandraQueryCreator(tree, parameterAccessor, mappingContext);
CassandraQueryCreator queryCreator =
new CassandraQueryCreator(tree, parameterAccessor, this.mappingContext);
Query query = queryCreator.createQuery();
@@ -158,9 +155,7 @@ class QueryStatementCreator {
query = query.limit(tree.getMaxResults());
}
if (this.queryMethod.getQueryAnnotation().map(org.springframework.data.cassandra.repository.Query::allowFiltering)
.orElse(false)) {
if (allowsFiltering()) {
query = query.withAllowFiltering();
}
@@ -175,11 +170,18 @@ class QueryStatementCreator {
}
return function.apply(query);
} catch (RuntimeException e) {
throw QueryCreationException.create(queryMethod, e);
} catch (RuntimeException cause) {
throw QueryCreationException.create(this.queryMethod, cause);
}
}
private boolean allowsFiltering() {
return this.queryMethod.getQueryAnnotation()
.map(org.springframework.data.cassandra.repository.Query::allowFiltering)
.orElse(false);
}
/**
* Create a {@link Statement} from a {@link StringBasedQuery} and apply query options.
*
@@ -199,7 +201,8 @@ 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());
}
@@ -209,8 +212,8 @@ class QueryStatementCreator {
}
return queryToUse;
} catch (RuntimeException e) {
throw QueryCreationException.create(this.queryMethod, e);
} catch (RuntimeException cause) {
throw QueryCreationException.create(this.queryMethod, cause);
}
}
}

View File

@@ -15,11 +15,12 @@
*/
package org.springframework.data.cassandra.repository.query;
import java.util.List;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import reactor.core.publisher.Mono;
import java.util.List;
import reactor.core.publisher.Mono;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.cassandra.core.ReactiveCassandraOperations;
@@ -103,7 +104,7 @@ interface ReactiveCassandraQueryExecution {
@Override
public Object execute(Statement statement, Class<?> type) {
Mono<List<Row>> rows = operations.getReactiveCqlOperations().queryForRows(statement).buffer(2).next();
Mono<List<Row>> rows = this.operations.getReactiveCqlOperations().queryForRows(statement).buffer(2).next();
return rows.map(it -> {
@@ -115,9 +116,10 @@ interface ReactiveCassandraQueryExecution {
Row row = it.get(0);
if (ProjectionUtil.isCountProjection(row)) {
if (ProjectionUtil.qualifiesAsCountProjection(row)) {
Object object = row.getObject(0);
return ((Number) object).longValue() > 0;
}
}

View File

@@ -112,7 +112,7 @@ public class ReactivePartTreeCassandraQuery extends AbstractReactiveCassandraQue
*/
@Override
protected boolean isCountQuery() {
return tree.isCountProjection();
return getTree().isCountProjection();
}
/* (non-Javadoc)
@@ -120,6 +120,6 @@ public class ReactivePartTreeCassandraQuery extends AbstractReactiveCassandraQue
*/
@Override
protected boolean isExistsQuery() {
return tree.isExistsProjection();
return getTree().isExistsProjection();
}
}

View File

@@ -59,7 +59,8 @@ public class ReactiveStringBasedCassandraQuery extends AbstractReactiveCassandra
ReactiveCassandraOperations operations, SpelExpressionParser expressionParser,
EvaluationContextProvider evaluationContextProvider) {
this(queryMethod.getRequiredAnnotatedQuery(), queryMethod, operations, expressionParser, evaluationContextProvider);
this(queryMethod.getRequiredAnnotatedQuery(), queryMethod, operations, expressionParser,
evaluationContextProvider);
}
/**
@@ -94,7 +95,6 @@ public class ReactiveStringBasedCassandraQuery extends AbstractReactiveCassandra
throw new IllegalArgumentException(String.format(COUNT_AND_EXISTS, method));
}
} else {
this.isCountQuery = false;
this.isExistsQuery = false;
}
@@ -117,7 +117,7 @@ public class ReactiveStringBasedCassandraQuery extends AbstractReactiveCassandra
*/
@Override
protected boolean isCountQuery() {
return isCountQuery;
return this.isCountQuery;
}
/* (non-Javadoc)
@@ -125,6 +125,6 @@ public class ReactiveStringBasedCassandraQuery extends AbstractReactiveCassandra
*/
@Override
protected boolean isExistsQuery() {
return isExistsQuery;
return this.isExistsQuery;
}
}

View File

@@ -57,7 +57,8 @@ public class StringBasedCassandraQuery extends AbstractCassandraQuery {
public StringBasedCassandraQuery(CassandraQueryMethod queryMethod, CassandraOperations operations,
SpelExpressionParser expressionParser, EvaluationContextProvider evaluationContextProvider) {
this(queryMethod.getRequiredAnnotatedQuery(), queryMethod, operations, expressionParser, evaluationContextProvider);
this(queryMethod.getRequiredAnnotatedQuery(), queryMethod, operations, expressionParser,
evaluationContextProvider);
}
/**
@@ -90,7 +91,6 @@ public class StringBasedCassandraQuery extends AbstractCassandraQuery {
throw new IllegalArgumentException(String.format(COUNT_AND_EXISTS, method));
}
} else {
this.isCountQuery = false;
this.isExistsQuery = false;
}
@@ -113,7 +113,7 @@ public class StringBasedCassandraQuery extends AbstractCassandraQuery {
*/
@Override
protected boolean isCountQuery() {
return isCountQuery;
return this.isCountQuery;
}
/* (non-Javadoc)
@@ -121,6 +121,6 @@ public class StringBasedCassandraQuery extends AbstractCassandraQuery {
*/
@Override
protected boolean isExistsQuery() {
return isExistsQuery;
return this.isExistsQuery;
}
}

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.cassandra.core;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.cassandra.core.query.Criteria.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.data.cassandra.core.query.Criteria.where;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -25,6 +25,7 @@ import java.util.concurrent.Future;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.cql.AsyncCqlTemplate;
import org.springframework.data.cassandra.core.query.CassandraPageRequest;

View File

@@ -15,9 +15,9 @@
*/
package org.springframework.data.cassandra.core;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
import static org.springframework.data.cassandra.core.query.Criteria.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeTrue;
import static org.springframework.data.cassandra.core.query.Criteria.where;
import java.util.Arrays;
import java.util.Collections;
@@ -30,6 +30,7 @@ import java.util.stream.Stream;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.cql.CqlTemplate;
import org.springframework.data.cassandra.core.mapping.BasicMapId;

View File

@@ -15,11 +15,14 @@
*/
package org.springframework.data.cassandra.core;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.List;
@@ -33,6 +36,7 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.cassandra.CassandraConnectionFailureException;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.data.cassandra.domain.User;

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.cassandra.core;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.cassandra.core.query.Criteria.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.data.cassandra.core.query.Criteria.where;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
@@ -25,6 +25,7 @@ import reactor.test.StepVerifier.FirstStep;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.cql.ReactiveCqlTemplate;
import org.springframework.data.cassandra.core.cql.session.DefaultBridgedReactiveSession;

View File

@@ -15,18 +15,20 @@
*/
package org.springframework.data.cassandra.core;
import static org.assertj.core.api.Assertions.*;
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.*;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Collections;
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;
@@ -34,6 +36,7 @@ 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;

View File

@@ -15,13 +15,14 @@
*/
package org.springframework.data.cassandra.core;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.cassandra.repository;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeTrue;
import java.time.LocalDate;
import java.util.ArrayList;
@@ -26,10 +26,10 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
@@ -55,6 +55,8 @@ import org.springframework.data.util.Version;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.assertj.core.api.Assertions;
import com.datastax.driver.core.Session;
/**

View File

@@ -15,17 +15,18 @@
*/
package org.springframework.data.cassandra.repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.reactivestreams.Publisher;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;

View File

@@ -15,7 +15,8 @@
*/
package org.springframework.data.cassandra.repository.isolated;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.offset;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -31,6 +32,7 @@ import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.SchemaAction;

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.cassandra.repository.query;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import java.lang.reflect.Method;
import java.util.Arrays;
@@ -30,6 +30,7 @@ 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;

View File

@@ -15,16 +15,15 @@
*/
package org.springframework.data.cassandra.repository.query;
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 static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import java.lang.reflect.Method;
import java.util.Arrays;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -32,6 +31,7 @@ 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,6 +49,8 @@ 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}.
*

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.cassandra.repository.query;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import java.lang.reflect.Method;
@@ -25,6 +25,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.cassandra.ReactiveSession;
import org.springframework.data.cassandra.core.ReactiveCassandraOperations;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;