Introduce KeyspaceProvider to StatementFactory.

StatementFactory now accepts a KeyspaceProvider to determine a specific Keyspace for a built statement.

StatementFactory can be obtained through CassandraTemplate and its async/reactive variants.

Closes #1275
This commit is contained in:
Mark Paluch
2024-07-24 15:26:40 +02:00
parent 24e1564f4f
commit 0cd9b43620
10 changed files with 282 additions and 187 deletions

View File

@@ -27,6 +27,7 @@ import java.util.stream.StreamSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -39,20 +40,7 @@ import org.springframework.data.cassandra.SessionFactory;
import org.springframework.data.cassandra.core.EntityOperations.AdaptibleEntity;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.cql.AsyncCqlOperations;
import org.springframework.data.cassandra.core.cql.AsyncCqlTemplate;
import org.springframework.data.cassandra.core.cql.AsyncPreparedStatementCreator;
import org.springframework.data.cassandra.core.cql.AsyncResultSetExtractor;
import org.springframework.data.cassandra.core.cql.AsyncSessionCallback;
import org.springframework.data.cassandra.core.cql.CassandraAccessor;
import org.springframework.data.cassandra.core.cql.CqlProvider;
import org.springframework.data.cassandra.core.cql.PreparedStatementBinder;
import org.springframework.data.cassandra.core.cql.QueryExtractorDelegate;
import org.springframework.data.cassandra.core.cql.QueryOptions;
import org.springframework.data.cassandra.core.cql.RowCallbackHandler;
import org.springframework.data.cassandra.core.cql.RowMapper;
import org.springframework.data.cassandra.core.cql.SingleColumnRowMapper;
import org.springframework.data.cassandra.core.cql.WriteOptions;
import org.springframework.data.cassandra.core.cql.*;
import org.springframework.data.cassandra.core.cql.session.DefaultSessionFactory;
import org.springframework.data.cassandra.core.cql.util.StatementBuilder;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
@@ -244,6 +232,17 @@ public class AsyncCassandraTemplate
return this.converter;
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
* @return the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
* @see StatementFactory
* @since 2.1
*/
public StatementFactory getStatementFactory() {
return this.statementFactory;
}
/**
* Returns whether this instance is configured to use {@link PreparedStatement prepared statements}. If enabled
* (default), then all persistence methods (such as {@link #select}, {@link #update}, and others) will make use of
@@ -300,17 +299,6 @@ public class AsyncCassandraTemplate
return getEntityOperations().getRequiredPersistentEntity(entityType);
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
* @return the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
* @see StatementFactory
* @since 2.1
*/
protected StatementFactory getStatementFactory() {
return this.statementFactory;
}
private CqlIdentifier getTableName(Class<?> entityClass) {
return getEntityOperations().getTableName(entityClass);
}

View File

@@ -19,7 +19,6 @@ import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.convert.UpdateMapper;
import org.springframework.data.cassandra.core.cql.QueryOptions;
import org.springframework.data.cassandra.core.cql.WriteOptions;
import org.springframework.data.cassandra.core.mapping.BasicCassandraPersistentEntity;
@@ -66,7 +65,7 @@ class CassandraBatchTemplate implements CassandraBatchOperations {
* @param batchType must not be {@literal null}.
* @since 3.2.6
*/
CassandraBatchTemplate(CassandraOperations operations, BatchType batchType) {
CassandraBatchTemplate(CassandraTemplate operations, BatchType batchType) {
Assert.notNull(operations, "CassandraOperations must not be null");
Assert.notNull(batchType, "BatchType must not be null");
@@ -75,7 +74,7 @@ class CassandraBatchTemplate implements CassandraBatchOperations {
this.batch = BatchStatement.builder(batchType);
this.converter = operations.getConverter();
this.mappingContext = this.converter.getMappingContext();
this.statementFactory = new StatementFactory(new UpdateMapper(converter));
this.statementFactory = operations.getStatementFactory();
}
/**

View File

@@ -23,6 +23,7 @@ import java.util.stream.Stream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -35,20 +36,7 @@ import org.springframework.data.cassandra.SessionFactory;
import org.springframework.data.cassandra.core.EntityOperations.AdaptibleEntity;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.convert.QueryMapper;
import org.springframework.data.cassandra.core.convert.UpdateMapper;
import org.springframework.data.cassandra.core.cql.CassandraAccessor;
import org.springframework.data.cassandra.core.cql.CqlOperations;
import org.springframework.data.cassandra.core.cql.CqlProvider;
import org.springframework.data.cassandra.core.cql.CqlTemplate;
import org.springframework.data.cassandra.core.cql.PreparedStatementBinder;
import org.springframework.data.cassandra.core.cql.PreparedStatementCreator;
import org.springframework.data.cassandra.core.cql.QueryExtractorDelegate;
import org.springframework.data.cassandra.core.cql.QueryOptions;
import org.springframework.data.cassandra.core.cql.RowMapper;
import org.springframework.data.cassandra.core.cql.SessionCallback;
import org.springframework.data.cassandra.core.cql.SingleColumnRowMapper;
import org.springframework.data.cassandra.core.cql.WriteOptions;
import org.springframework.data.cassandra.core.cql.*;
import org.springframework.data.cassandra.core.cql.session.DefaultSessionFactory;
import org.springframework.data.cassandra.core.cql.util.StatementBuilder;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
@@ -193,7 +181,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
this.converter = converter;
this.cqlOperations = cqlOperations;
this.entityOperations = new EntityOperations(converter);
this.statementFactory = new StatementFactory(new QueryMapper(converter), new UpdateMapper(converter));
this.statementFactory = new StatementFactory(converter);
this.eventDelegate = new EntityLifecycleEventDelegate();
}
@@ -246,6 +234,17 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
return this.converter;
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
* @return the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
* @see org.springframework.data.cassandra.core.StatementFactory
* @since 2.1
*/
public StatementFactory getStatementFactory() {
return this.statementFactory;
}
/**
* Returns whether this instance is configured to use {@link PreparedStatement prepared statements}. If enabled
* (default), then all persistence methods (such as {@link #select}, {@link #update}, and others) will make use of
@@ -301,17 +300,6 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP
return getEntityOperations().getRequiredPersistentEntity(entityType);
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
* @return the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
* @see org.springframework.data.cassandra.core.StatementFactory
* @since 2.1
*/
protected StatementFactory getStatementFactory() {
return this.statementFactory;
}
@Override
public CqlIdentifier getTableName(Class<?> entityClass) {
return getEntityOperations().getTableName(entityClass);

View File

@@ -26,7 +26,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.convert.UpdateMapper;
import org.springframework.data.cassandra.core.cql.QueryOptions;
import org.springframework.data.cassandra.core.cql.WriteOptions;
import org.springframework.data.cassandra.core.mapping.BasicCassandraPersistentEntity;
@@ -74,7 +73,7 @@ class ReactiveCassandraBatchTemplate implements ReactiveCassandraBatchOperations
* @param batchType must not be {@literal null}.
* @since 3.2.6
*/
ReactiveCassandraBatchTemplate(ReactiveCassandraOperations operations, BatchType batchType) {
ReactiveCassandraBatchTemplate(ReactiveCassandraTemplate operations, BatchType batchType) {
Assert.notNull(operations, "CassandraOperations must not be null");
Assert.notNull(batchType, "BatchType must not be null");
@@ -83,7 +82,7 @@ class ReactiveCassandraBatchTemplate implements ReactiveCassandraBatchOperations
this.batch = BatchStatement.builder(batchType);
this.converter = operations.getConverter();
this.mappingContext = this.converter.getMappingContext();
this.statementFactory = new StatementFactory(new UpdateMapper(converter));
this.statementFactory = operations.getStatementFactory();
}
private void assertNotExecuted() {

View File

@@ -27,6 +27,7 @@ import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.reactivestreams.Publisher;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -41,18 +42,7 @@ import org.springframework.data.cassandra.ReactiveSessionFactory;
import org.springframework.data.cassandra.core.EntityOperations.AdaptibleEntity;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.cql.CassandraAccessor;
import org.springframework.data.cassandra.core.cql.CqlProvider;
import org.springframework.data.cassandra.core.cql.PreparedStatementBinder;
import org.springframework.data.cassandra.core.cql.QueryExtractorDelegate;
import org.springframework.data.cassandra.core.cql.QueryOptions;
import org.springframework.data.cassandra.core.cql.ReactiveCqlOperations;
import org.springframework.data.cassandra.core.cql.ReactiveCqlTemplate;
import org.springframework.data.cassandra.core.cql.ReactivePreparedStatementCreator;
import org.springframework.data.cassandra.core.cql.ReactiveSessionCallback;
import org.springframework.data.cassandra.core.cql.RowMapper;
import org.springframework.data.cassandra.core.cql.SingleColumnRowMapper;
import org.springframework.data.cassandra.core.cql.WriteOptions;
import org.springframework.data.cassandra.core.cql.*;
import org.springframework.data.cassandra.core.cql.session.DefaultReactiveSessionFactory;
import org.springframework.data.cassandra.core.cql.util.StatementBuilder;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
@@ -253,6 +243,17 @@ public class ReactiveCassandraTemplate
return this.converter;
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
* @return the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
* @see org.springframework.data.cassandra.core.StatementFactory
* @since 2.1
*/
public StatementFactory getStatementFactory() {
return this.statementFactory;
}
/**
* Returns whether this instance is configured to use {@link PreparedStatement prepared statements}. If enabled
* (default), then all persistence methods (such as {@link #select}, {@link #update}, and others) will make use of
@@ -309,17 +310,6 @@ public class ReactiveCassandraTemplate
return getEntityOperations().getRequiredPersistentEntity(entityType);
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
* @return the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
* @see org.springframework.data.cassandra.core.StatementFactory
* @since 2.1
*/
protected StatementFactory getStatementFactory() {
return this.statementFactory;
}
CqlIdentifier getTableName(Class<?> entityClass) {
return getRequiredPersistentEntity(entityClass).getTableName();
}

View File

@@ -37,6 +37,7 @@ import org.springframework.data.cassandra.core.cql.QueryOptionsUtil.CqlStatement
import org.springframework.data.cassandra.core.cql.WriteOptions;
import org.springframework.data.cassandra.core.cql.util.StatementBuilder;
import org.springframework.data.cassandra.core.cql.util.TermFactory;
import org.springframework.data.cassandra.core.mapping.BasicCassandraPersistentEntity;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.core.mapping.PersistentPropertyTranslator;
@@ -64,6 +65,7 @@ import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.projection.EntityProjection;
import org.springframework.data.projection.ProjectionInformation;
import org.springframework.data.util.Predicates;
import org.springframework.data.util.ProxyUtils;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -108,6 +110,8 @@ public class StatementFactory {
private final UpdateMapper updateMapper;
private KeyspaceProvider keyspaceProvider = KeyspaceProviders.EMPTY_KEYSPACE;
/**
* Create {@link StatementFactory} given {@link CassandraConverter}.
*
@@ -117,6 +121,7 @@ public class StatementFactory {
public StatementFactory(CassandraConverter converter) {
Assert.notNull(converter, "CassandraConverter must not be null");
this.cassandraConverter = converter;
UpdateMapper updateMapper = new UpdateMapper(converter);
@@ -169,20 +174,34 @@ public class StatementFactory {
return this.updateMapper;
}
/**
* Sets the {@link KeyspaceProvider} to determine the {@link CqlIdentifier keyspace} for a
* {@link CassandraPersistentEntity entity}-related statement.
*
* @param keyspaceProvider the keyspace provider to use, must not be {@literal null}.
* @since 4.4
*/
public void setKeyspaceProvider(KeyspaceProvider keyspaceProvider) {
Assert.notNull(keyspaceProvider, "KeyspaceProvider must not be null");
this.keyspaceProvider = keyspaceProvider;
}
/**
* 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 persistentEntity {@link CassandraPersistentEntity entity} to count; must not be {@literal null}.
* @param entity {@link CassandraPersistentEntity entity} to count; must not be {@literal null}.
* @return the select builder.
* @since 2.1
*/
public StatementBuilder<Select> count(Query query, CassandraPersistentEntity<?> persistentEntity) {
public StatementBuilder<Select> count(Query query, CassandraPersistentEntity<?> entity) {
Assert.notNull(query, "Query must not be null");
Assert.notNull(persistentEntity, "CassandraPersistentEntity must not be null");
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
return count(query, persistentEntity, persistentEntity.getTableName());
return count(query, entity, entity.getTableName());
}
/**
@@ -208,18 +227,18 @@ public class StatementFactory {
* {@link UpdateOptions}.
*
* @param id must not be {@literal null}.
* @param persistentEntity must not be {@literal null}.
* @param entity must not be {@literal null}.
* @param tableName must not be {@literal null}.
* @return the select builder.
*/
public StatementBuilder<Select> selectOneById(Object id, CassandraPersistentEntity<?> persistentEntity,
public StatementBuilder<Select> selectOneById(Object id, CassandraPersistentEntity<?> entity,
CqlIdentifier tableName) {
Where where = new Where();
cassandraConverter.write(id, where, persistentEntity);
cassandraConverter.write(id, where, entity);
return StatementBuilder.of(QueryBuilder.selectFrom(tableName).all().limit(1))
return StatementBuilder.of(QueryBuilder.selectFrom(getKeyspace(entity, tableName), tableName).all().limit(1))
.bind((statement, factory) -> statement.where(toRelations(where, factory)));
}
@@ -227,38 +246,37 @@ public class StatementFactory {
* Create a {@literal SELECT} statement by mapping {@link Query} to {@link Select}.
*
* @param query must not be {@literal null}.
* @param persistentEntity must not be {@literal null}.
* @param entity must not be {@literal null}.
* @return the select builder.
*/
public StatementBuilder<Select> select(Query query, CassandraPersistentEntity<?> persistentEntity) {
public StatementBuilder<Select> select(Query query, CassandraPersistentEntity<?> entity) {
Assert.notNull(query, "Query must not be null");
Assert.notNull(persistentEntity, "CassandraPersistentEntity must not be null");
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
return select(query, persistentEntity, persistentEntity.getTableName());
return select(query, entity, entity.getTableName());
}
/**
* Create a {@literal SELECT} statement by mapping {@link Query} to {@link Select}.
*
* @param query must not be {@literal null}.
* @param persistentEntity must not be {@literal null}.
* @param entity must not be {@literal null}.
* @param tableName must not be {@literal null}.
* @return the select builder.
* @since 2.1
*/
public StatementBuilder<Select> select(Query query, CassandraPersistentEntity<?> persistentEntity,
CqlIdentifier tableName) {
public StatementBuilder<Select> select(Query query, CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
Assert.notNull(query, "Query must not be null");
Assert.notNull(persistentEntity, "CassandraPersistentEntity must not be null");
Assert.notNull(persistentEntity, "Table name must not be null");
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
Assert.notNull(entity, "Table name must not be null");
Filter filter = getQueryMapper().getMappedObject(query, persistentEntity);
Filter filter = getQueryMapper().getMappedObject(query, entity);
List<Selector> selectors = getQueryMapper().getMappedSelectors(query.getColumns(), persistentEntity);
List<Selector> selectors = getQueryMapper().getMappedSelectors(query.getColumns(), entity);
return createSelect(query, persistentEntity, filter, selectors, tableName);
return createSelect(query, entity, filter, selectors, tableName);
}
/**
@@ -274,9 +292,9 @@ public class StatementFactory {
Assert.notNull(objectToInsert, "Object to builder must not be null");
Assert.notNull(options, "WriteOptions must not be null");
CassandraPersistentEntity<?> persistentEntity = cassandraConverter.getMappingContext()
CassandraPersistentEntity<?> entity = cassandraConverter.getMappingContext()
.getRequiredPersistentEntity(objectToInsert.getClass());
return insert(objectToInsert, options, persistentEntity, persistentEntity.getTableName());
return insert(objectToInsert, options, entity, entity.getTableName());
}
/**
@@ -285,15 +303,15 @@ public class StatementFactory {
* @param tableName the table name, must not be empty and not {@literal null}.
* @param objectToInsert the object to save, must not be {@literal null}.
* @param options optional {@link WriteOptions} to apply to the {@link Insert} statement, may be {@literal null}.
* @param persistentEntity the {@link CassandraPersistentEntity} to write insert values.
* @param entity the {@link CassandraPersistentEntity} to write insert values.
* @return the select builder.
*/
public StatementBuilder<RegularInsert> insert(Object objectToInsert, WriteOptions options,
CassandraPersistentEntity<?> persistentEntity, CqlIdentifier tableName) {
CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
Assert.notNull(tableName, "TableName must not be null");
Assert.notNull(objectToInsert, "Object to insert must not be null");
Assert.notNull(persistentEntity, "CassandraPersistentEntity must not be null");
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
boolean insertNulls;
@@ -304,10 +322,11 @@ public class StatementFactory {
}
Map<CqlIdentifier, Object> object = new LinkedHashMap<>();
cassandraConverter.write(objectToInsert, object, persistentEntity);
cassandraConverter.write(objectToInsert, object, entity);
StatementBuilder<RegularInsert> builder = StatementBuilder
.of(QueryBuilder.insertInto(tableName).valuesByIds(Collections.emptyMap())).bind((statement, factory) -> {
.of(QueryBuilder.insertInto(getKeyspace(entity, tableName), tableName).valuesByIds(Collections.emptyMap()))
.bind((statement, factory) -> {
Map<CqlIdentifier, Term> values = createTerms(insertNulls, object, factory);
CqlStatementOptionsAccessor<Insert> accessor = factory.ifBoundOrInline(
@@ -342,17 +361,17 @@ public class StatementFactory {
* Create an {@literal UPDATE} statement by mapping {@link Query} to {@link Update}.
*
* @param query must not be {@literal null}.
* @param persistentEntity must not be {@literal null}.
* @param entity must not be {@literal null}.
* @return the update builder.
*/
public StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update(Query query, Update update,
CassandraPersistentEntity<?> persistentEntity) {
CassandraPersistentEntity<?> entity) {
Assert.notNull(query, "Query must not be null");
Assert.notNull(update, "Update must not be null");
Assert.notNull(persistentEntity, "CassandraPersistentEntity must not be null");
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
return update(query, update, persistentEntity, persistentEntity.getTableName());
return update(query, update, entity, entity.getTableName());
}
/**
@@ -360,25 +379,26 @@ public class StatementFactory {
*
* @param query must not be {@literal null}.
* @param update must not be {@literal null}.
* @param persistentEntity must not be {@literal null}.
* @param entity must not be {@literal null}.
* @param tableName must not be {@literal null}.
* @return the update builder.
* @since 2.1
*/
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update(Query query, Update update,
CassandraPersistentEntity<?> persistentEntity, CqlIdentifier tableName) {
CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
Assert.notNull(query, "Query must not be null");
Assert.notNull(update, "Update must not be null");
Assert.notNull(persistentEntity, "CassandraPersistentEntity must not be null");
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
Assert.notNull(tableName, "Table name must not be null");
Filter filter = getQueryMapper().getMappedObject(query, persistentEntity);
Filter filter = getQueryMapper().getMappedObject(query, entity);
Update mappedUpdate = getUpdateMapper().getMappedObject(update, persistentEntity);
Update mappedUpdate = getUpdateMapper().getMappedObject(update, entity);
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> builder = update(tableName, mappedUpdate,
filter, query.getQueryOptions().filter(WriteOptions.class::isInstance).map(WriteOptions.class::cast));
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> builder = update(entity, tableName,
mappedUpdate, filter,
query.getQueryOptions().filter(WriteOptions.class::isInstance).map(WriteOptions.class::cast));
query.getQueryOptions().filter(UpdateOptions.class::isInstance).map(UpdateOptions.class::cast)
.map(UpdateOptions::getIfCondition)
@@ -405,10 +425,10 @@ public class StatementFactory {
Assert.notNull(objectToUpdate, "Object to builder must not be null");
Assert.notNull(options, "WriteOptions must not be null");
CassandraPersistentEntity<?> persistentEntity = cassandraConverter.getMappingContext()
CassandraPersistentEntity<?> entity = cassandraConverter.getMappingContext()
.getRequiredPersistentEntity(objectToUpdate.getClass());
return update(objectToUpdate, options, persistentEntity, persistentEntity.getTableName());
return update(objectToUpdate, options, entity, entity.getTableName());
}
/**
@@ -437,7 +457,7 @@ public class StatementFactory {
where.forEach((cqlIdentifier, o) -> object.remove(cqlIdentifier));
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> builder = StatementBuilder
.of(QueryBuilder.update(tableName).set().where()).bind((statement, factory) -> {
.of(QueryBuilder.update(getKeyspace(entity, tableName), tableName).set().where()).bind((statement, factory) -> {
CqlStatementOptionsAccessor<UpdateStart> accessor = factory.ifBoundOrInline(
bindings -> CqlStatementOptionsAccessor.ofUpdate(bindings, (UpdateStart) statement),
@@ -462,18 +482,17 @@ public class StatementFactory {
* {@link UpdateOptions}.
*
* @param id must not be {@literal null}.
* @param persistentEntity must not be {@literal null}.
* @param entity must not be {@literal null}.
* @param tableName must not be {@literal null}.
* @return the delete builder.
*/
public StatementBuilder<Delete> deleteById(Object id, CassandraPersistentEntity<?> persistentEntity,
CqlIdentifier tableName) {
public StatementBuilder<Delete> deleteById(Object id, CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
Where where = new Where();
cassandraConverter.write(id, where, persistentEntity);
cassandraConverter.write(id, where, entity);
return StatementBuilder.of(QueryBuilder.deleteFrom(tableName).where())
return StatementBuilder.of(QueryBuilder.deleteFrom(getKeyspace(entity, tableName), tableName).where())
.bind((statement, factory) -> statement.where(toRelations(where, factory)));
}
@@ -481,37 +500,36 @@ public class StatementFactory {
* Create a {@literal DELETE} statement by mapping {@link Query} to {@link Delete}.
*
* @param query must not be {@literal null}.
* @param persistentEntity must not be {@literal null}.
* @param entity must not be {@literal null}.
* @return the delete builder.
*/
public StatementBuilder<Delete> delete(Query query, CassandraPersistentEntity<?> persistentEntity) {
public StatementBuilder<Delete> delete(Query query, CassandraPersistentEntity<?> entity) {
Assert.notNull(query, "Query must not be null");
Assert.notNull(persistentEntity, "CassandraPersistentEntity must not be null");
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
return delete(query, persistentEntity, persistentEntity.getTableName());
return delete(query, entity, entity.getTableName());
}
/**
* Create a {@literal DELETE} statement by mapping {@link Query} to {@link Delete}.
*
* @param query must not be {@literal null}.
* @param persistentEntity must not be {@literal null}.
* @param entity must not be {@literal null}.
* @param tableName must not be {@literal null}.
* @return the delete builder.
* @see 2.1
*/
public StatementBuilder<Delete> delete(Query query, CassandraPersistentEntity<?> persistentEntity,
CqlIdentifier tableName) {
public StatementBuilder<Delete> delete(Query query, CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
Assert.notNull(query, "Query must not be null");
Assert.notNull(persistentEntity, "CassandraPersistentEntity must not be null");
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
Assert.notNull(tableName, "Table name must not be null");
Filter filter = getQueryMapper().getMappedObject(query, persistentEntity);
List<CqlIdentifier> columnNames = getQueryMapper().getMappedColumnNames(query.getColumns(), persistentEntity);
Filter filter = getQueryMapper().getMappedObject(query, entity);
List<CqlIdentifier> columnNames = getQueryMapper().getMappedColumnNames(query.getColumns(), entity);
StatementBuilder<Delete> builder = delete(columnNames, tableName, filter,
StatementBuilder<Delete> builder = delete(columnNames, entity, tableName, filter,
query.getQueryOptions().filter(WriteOptions.class::isInstance).map(WriteOptions.class::cast));
query.getQueryOptions().filter(DeleteOptions.class::isInstance).map(DeleteOptions.class::cast)
@@ -543,8 +561,11 @@ public class StatementFactory {
Where where = new Where();
entityWriter.write(entity, where);
BasicCassandraPersistentEntity<?> persistentEntity = cassandraConverter.getMappingContext()
.getRequiredPersistentEntity(ProxyUtils.getUserClass(entity.getClass()));
StatementBuilder<Delete> builder = StatementBuilder.of(QueryBuilder.deleteFrom(tableName).where())
StatementBuilder<Delete> builder = StatementBuilder
.of(QueryBuilder.deleteFrom(getKeyspace(persistentEntity, tableName), tableName).where())
.bind((statement, factory) -> {
Delete statementToUse;
@@ -595,9 +616,9 @@ public class StatementFactory {
PersistentPropertyTranslator translator = PersistentPropertyTranslator.create(domainType,
Predicates.negate(CassandraPersistentProperty::hasExplicitColumnName));
CassandraPersistentEntity<?> persistentEntity = getQueryMapper().getConverter().getMappingContext()
CassandraPersistentEntity<?> entity = getQueryMapper().getConverter().getMappingContext()
.getRequiredPersistentEntity(projection.getMappedType());
for (CassandraPersistentProperty property : persistentEntity) {
for (CassandraPersistentProperty property : entity) {
columns.include(translator.translate(property).getColumnName());
}
}
@@ -630,7 +651,7 @@ public class StatementFactory {
Sort sort = Optional.of(query.getSort()).map(querySort -> getQueryMapper().getMappedSort(querySort, entity))
.orElse(Sort.unsorted());
StatementBuilder<Select> select = createSelectAndOrder(selectors, tableName, filter, sort);
StatementBuilder<Select> select = createSelectAndOrder(selectors, entity, tableName, filter, sort);
if (query.isAllowFiltering()) {
select.apply(Select::allowFiltering);
@@ -651,13 +672,18 @@ public class StatementFactory {
return select;
}
private static StatementBuilder<Select> createSelectAndOrder(List<Selector> selectors, CqlIdentifier from,
Filter filter, Sort sort) {
@Nullable
private CqlIdentifier getKeyspace(CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
return keyspaceProvider.getKeyspace(entity, tableName);
}
private StatementBuilder<Select> createSelectAndOrder(List<Selector> selectors, CassandraPersistentEntity<?> entity,
CqlIdentifier from, Filter filter, Sort sort) {
Select select;
if (selectors.isEmpty()) {
select = QueryBuilder.selectFrom(from).all();
select = QueryBuilder.selectFrom(getKeyspace(entity, from), from).all();
} else {
List<com.datastax.oss.driver.api.querybuilder.select.Selector> mappedSelectors = new ArrayList<>(
@@ -668,7 +694,7 @@ public class StatementFactory {
mappedSelectors.add(orElseGet);
}
select = QueryBuilder.selectFrom(from).selectors(mappedSelectors);
select = QueryBuilder.selectFrom(getKeyspace(entity, from), from).selectors(mappedSelectors);
}
StatementBuilder<Select> builder = StatementBuilder.of(select);
@@ -726,10 +752,11 @@ public class StatementFactory {
.column(CqlIdentifier.fromInternal(selector.getExpression()));
}
private static StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update(CqlIdentifier table,
Update mappedUpdate, Filter filter, Optional<WriteOptions> optionalOptions) {
private StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update(
CassandraPersistentEntity<?> entity, CqlIdentifier table, Update mappedUpdate, Filter filter,
Optional<WriteOptions> optionalOptions) {
UpdateStart updateStart = QueryBuilder.update(table);
UpdateStart updateStart = QueryBuilder.update(getKeyspace(entity, table), table);
return StatementBuilder.of((com.datastax.oss.driver.api.querybuilder.update.Update) updateStart)
.bind((statement, factory) -> {
@@ -882,10 +909,10 @@ public class StatementFactory {
return Assignment.append(updateOp.toCqlIdentifier(), termFactory.create(updateOp.getValue()));
}
private StatementBuilder<Delete> delete(List<CqlIdentifier> columnNames, CqlIdentifier from, Filter filter,
Optional<WriteOptions> optionsOptional) {
private StatementBuilder<Delete> delete(List<CqlIdentifier> columnNames, CassandraPersistentEntity<?> entity,
CqlIdentifier from, Filter filter, Optional<WriteOptions> optionsOptional) {
DeleteSelection select = QueryBuilder.deleteFrom(from);
DeleteSelection select = QueryBuilder.deleteFrom(getKeyspace(entity, from), from);
for (CqlIdentifier columnName : columnNames) {
select = select.column(columnName);
@@ -1201,4 +1228,38 @@ public class StatementFactory {
}
/**
* Function interface to determine a {@link CqlIdentifier keyspace} for a given {@link CassandraPersistentEntity} and
* {@code tableName}. Classes implementing this interface can choose to return a keyspace or {@code null} to use the
* default keyspace.
*
* @since 4.4
*/
@FunctionalInterface
public interface KeyspaceProvider {
/**
* Determine a {@link CqlIdentifier keyspace} for a given {@link CassandraPersistentEntity} and {@code tableName}.
*
* @param entity the persistent entity for which the operation is applied.
* @param tableName the table of the operation.
* @return a {@link CqlIdentifier keyspace} to use a dedicated keyspace for a
* {@link com.datastax.oss.driver.api.core.cql.Statement} or {@code null} to use the default session
* keyspace.
*/
@Nullable
CqlIdentifier getKeyspace(CassandraPersistentEntity<?> entity, CqlIdentifier tableName);
}
enum KeyspaceProviders implements KeyspaceProvider {
EMPTY_KEYSPACE {
@Nullable
@Override
public CqlIdentifier getKeyspace(CassandraPersistentEntity<?> entity, CqlIdentifier tableName) {
return null;
}
}
}
}

View File

@@ -259,6 +259,17 @@ public class AsyncCassandraTemplate
return this.converter;
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
* @return the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
* @see StatementFactory
* @since 2.1
*/
public StatementFactory getStatementFactory() {
return this.statementFactory;
}
/**
* Returns whether this instance is configured to use {@link PreparedStatement prepared statements}. If enabled
* (default), then all persistence methods (such as {@link #select}, {@link #update}, and others) will make use of
@@ -315,17 +326,6 @@ public class AsyncCassandraTemplate
return getEntityOperations().getRequiredPersistentEntity(entityType);
}
/**
* Returns the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
*
* @return the {@link StatementFactory} used by this template to construct and run Cassandra CQL statements.
* @see StatementFactory
* @since 2.1
*/
protected StatementFactory getStatementFactory() {
return this.statementFactory;
}
private CqlIdentifier getTableName(Class<?> entityClass) {
return getEntityOperations().getTableName(entityClass);
}

View File

@@ -56,7 +56,8 @@ public class PartTreeCassandraQuery extends AbstractCassandraQuery {
this.tree = new PartTree(queryMethod.getName(), queryMethod.getResultProcessor().getReturnedType().getDomainType());
this.mappingContext = operations.getConverter().getMappingContext();
this.statementFactory = new StatementFactory(new UpdateMapper(operations.getConverter()));
this.statementFactory = operations instanceof CassandraTemplate ct ? ct.getStatementFactory()
: new StatementFactory(new UpdateMapper(operations.getConverter()));
}
/**

View File

@@ -18,6 +18,7 @@ package org.springframework.data.cassandra.repository.query;
import reactor.core.publisher.Mono;
import org.springframework.data.cassandra.core.ReactiveCassandraOperations;
import org.springframework.data.cassandra.core.ReactiveCassandraTemplate;
import org.springframework.data.cassandra.core.StatementFactory;
import org.springframework.data.cassandra.core.convert.UpdateMapper;
import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
@@ -58,7 +59,8 @@ public class ReactivePartTreeCassandraQuery extends AbstractReactiveCassandraQue
this.tree = new PartTree(queryMethod.getName(), queryMethod.getResultProcessor().getReturnedType().getDomainType());
this.mappingContext = operations.getConverter().getMappingContext();
this.statementFactory = new StatementFactory(new UpdateMapper(operations.getConverter()));
this.statementFactory = operations instanceof ReactiveCassandraTemplate rct ? rct.getStatementFactory()
: new StatementFactory(new UpdateMapper(operations.getConverter()));
}
/**

View File

@@ -16,6 +16,7 @@
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.springframework.data.domain.Sort.Direction.*;
import java.time.Duration;
@@ -26,6 +27,7 @@ import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.cassandra.core.convert.CassandraConverter;
import org.springframework.data.cassandra.core.convert.MappingCassandraConverter;
@@ -37,7 +39,6 @@ import org.springframework.data.cassandra.core.cql.util.StatementBuilder.Paramet
import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.core.mapping.Column;
import org.springframework.data.cassandra.core.query.Columns;
import org.springframework.data.cassandra.core.query.Criteria;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.data.cassandra.core.query.Update;
import org.springframework.data.cassandra.domain.Group;
@@ -79,6 +80,17 @@ class StatementFactoryUnitTests {
assertThat(select.build(ParameterHandling.INLINE).getQuery()).isEqualTo("SELECT * FROM group");
}
@Test // GH-1275
void shouldConsiderKeyspaceForSelect() {
statementFactory.setKeyspaceProvider((entity, tableName) -> CqlIdentifier.fromCql("ks_" + tableName));
StatementBuilder<Select> select = statementFactory.select(Query.empty(),
converter.getMappingContext().getRequiredPersistentEntity(Group.class));
assertThat(select.build(ParameterHandling.INLINE).getQuery()).isEqualTo("SELECT * FROM ks_group.group");
}
@Test // DATACASS-708
void selectShouldApplyQueryOptions() {
@@ -98,7 +110,7 @@ class StatementFactoryUnitTests {
@Test // DATACASS-343
void shouldMapSelectQueryWithColumnsAndCriteria() {
Query query = Query.query(Criteria.where("foo").is("bar")).columns(Columns.from("age"));
Query query = Query.query(where("foo").is("bar")).columns(Columns.from("age"));
StatementBuilder<Select> select = statementFactory.select(query, groupEntity);
@@ -108,7 +120,7 @@ class StatementFactoryUnitTests {
@Test // DATACASS-549
void shouldMapSelectQueryNotEquals() {
Query query = Query.query(Criteria.where("foo").ne("bar")).columns(Columns.from("age"));
Query query = Query.query(where("foo").ne("bar")).columns(Columns.from("age"));
StatementBuilder<Select> select = statementFactory.select(query, groupEntity);
@@ -118,7 +130,7 @@ class StatementFactoryUnitTests {
@Test // DATACASS-549
void shouldMapSelectQueryIsNotNull() {
Query query = Query.query(Criteria.where("foo").isNotNull()).columns(Columns.from("age"));
Query query = Query.query(where("foo").isNotNull()).columns(Columns.from("age"));
StatementBuilder<Select> select = statementFactory.select(query, groupEntity);
@@ -152,7 +164,7 @@ class StatementFactoryUnitTests {
@Test // GH-1401
void shouldMapSelectQueryWithLimit() {
Query query = Query.query(Criteria.where("email").is("e@mail")).limit(Limit.of(10));
Query query = Query.query(where("email").is("e@mail")).limit(Limit.of(10));
StatementBuilder<Select> select = statementFactory.select(query,
converter.getMappingContext().getRequiredPersistentEntity(Group.class));
@@ -192,12 +204,12 @@ class StatementFactoryUnitTests {
@Test // GH-1172
void shouldMapSelectInQueryAsInlineValue() {
StatementBuilder<Select> select = statementFactory.select(Query.query(Criteria.where("foo").in("bar")),
StatementBuilder<Select> select = statementFactory.select(Query.query(where("foo").in("bar")),
groupEntity);
assertThat(select.build(ParameterHandling.INLINE).getQuery()).isEqualTo("SELECT * FROM group WHERE foo IN ('bar')");
select = statementFactory.select(Query.query(Criteria.where("foo").in("bar", "baz")), groupEntity);
select = statementFactory.select(Query.query(where("foo").in("bar", "baz")), groupEntity);
assertThat(select.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("SELECT * FROM group WHERE foo IN ('bar','baz')");
@@ -206,14 +218,14 @@ class StatementFactoryUnitTests {
@Test // GH-1172
void shouldMapSelectInQueryAsByIndexValue() {
StatementBuilder<Select> select = statementFactory.select(Query.query(Criteria.where("foo").in("bar")),
StatementBuilder<Select> select = statementFactory.select(Query.query(where("foo").in("bar")),
groupEntity);
SimpleStatement statement = select.build(ParameterHandling.BY_INDEX);
assertThat(statement.getQuery()).isEqualTo("SELECT * FROM group WHERE foo IN ?");
assertThat(statement.getPositionalValues()).containsOnly(Collections.singletonList("bar"));
select = statementFactory.select(Query.query(Criteria.where("foo").in("bar", "baz")), groupEntity);
select = statementFactory.select(Query.query(where("foo").in("bar", "baz")), groupEntity);
statement = select.build(ParameterHandling.BY_INDEX);
assertThat(statement.getQuery()).isEqualTo("SELECT * FROM group WHERE foo IN ?");
@@ -223,7 +235,7 @@ class StatementFactoryUnitTests {
@Test // GH-1172
void shouldMapSelectInQueryAsByNamedValue() {
StatementBuilder<Select> select = statementFactory.select(Query.query(Criteria.where("foo").in("bar")),
StatementBuilder<Select> select = statementFactory.select(Query.query(where("foo").in("bar")),
groupEntity);
SimpleStatement statement = select.build(ParameterHandling.BY_NAME);
@@ -231,7 +243,7 @@ class StatementFactoryUnitTests {
assertThat(statement.getNamedValues()).hasSize(1).containsEntry(CqlIdentifier.fromCql("p0"),
Collections.singletonList("bar"));
select = statementFactory.select(Query.query(Criteria.where("foo").in("bar", "baz")), groupEntity);
select = statementFactory.select(Query.query(where("foo").in("bar", "baz")), groupEntity);
statement = select.build(ParameterHandling.BY_NAME);
assertThat(statement.getQuery()).isEqualTo("SELECT * FROM group WHERE foo IN :p0");
@@ -254,7 +266,7 @@ class StatementFactoryUnitTests {
void shouldMapDeleteQueryWithTimestampColumns() {
DeleteOptions options = DeleteOptions.builder().timestamp(1234).build();
Query query = Query.query(Criteria.where("foo").is("bar")).queryOptions(options);
Query query = Query.query(where("foo").is("bar")).queryOptions(options);
StatementBuilder<Delete> delete = statementFactory.delete(query,
converter.getMappingContext().getRequiredPersistentEntity(Group.class));
@@ -267,7 +279,7 @@ class StatementFactoryUnitTests {
void deleteByQueryWithOptionsShouldRenderBindMarkers() {
DeleteOptions options = DeleteOptions.builder().timestamp(1234).build();
Query query = Query.query(Criteria.where("foo").is("bar")).queryOptions(options);
Query query = Query.query(where("foo").is("bar")).queryOptions(options);
StatementBuilder<Delete> delete = statementFactory.delete(query,
converter.getMappingContext().getRequiredPersistentEntity(Group.class));
@@ -295,6 +307,33 @@ class StatementFactoryUnitTests {
assertThat(statement.getPositionalValues()).containsExactly(1234L, "foo");
}
@Test // GH-1275
void shouldConsiderKeyspaceForDeleteByEntity() {
statementFactory.setKeyspaceProvider((entity, tableName) -> CqlIdentifier.fromCql("ks_" + tableName));
Person person = new Person();
person.id = "foo";
StatementBuilder<Delete> delete = statementFactory.delete(person, DeleteOptions.empty(), converter,
CqlIdentifier.fromCql("person"));
SimpleStatement statement = delete.build(ParameterHandling.BY_INDEX);
assertThat(statement.getQuery()).isEqualTo("DELETE FROM ks_person.person WHERE id=?");
}
@Test // GH-1275
void shouldConsiderKeyspaceForDelete() {
statementFactory.setKeyspaceProvider((entity, tableName) -> CqlIdentifier.fromCql("ks_" + tableName));
StatementBuilder<Delete> delete = statementFactory.delete(Query.query(where("foo").is("bar")), groupEntity);
SimpleStatement statement = delete.build(ParameterHandling.BY_INDEX);
assertThat(statement.getQuery()).isEqualTo("DELETE FROM ks_group.group WHERE foo=?");
}
@Test // DATACASS-708
void deleteShouldApplyQueryOptions() {
@@ -325,6 +364,20 @@ class StatementFactoryUnitTests {
assertThat(insert.build(ParameterHandling.INLINE).getQuery()).isEqualTo("INSERT INTO person (id) VALUES ('foo')");
}
@Test // GH-1275
void shouldConsiderKeyspaceForInsert() {
statementFactory.setKeyspaceProvider((entity, tableName) -> CqlIdentifier.fromCql("ks_" + tableName));
Person person = new Person();
person.id = "foo";
StatementBuilder<RegularInsert> insert = statementFactory.insert(person, WriteOptions.empty());
assertThat(insert.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("INSERT INTO ks_person.person (id) VALUES ('foo')");
}
@Test // DATACASS-708
void insertShouldApplyQueryOptions() {
@@ -415,7 +468,7 @@ class StatementFactoryUnitTests {
@Test // DATACASS-343
void shouldCreateSetUpdate() {
Query query = Query.query(Criteria.where("foo").is("bar"));
Query query = Query.query(where("foo").is("bar"));
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz").set("boo", "baa"), personEntity);
@@ -424,11 +477,25 @@ class StatementFactoryUnitTests {
.isEqualTo("UPDATE person SET first_name='baz', boo='baa' WHERE foo='bar'");
}
@Test // GH-1275
void shouldConsiderKeyspaceForCreateSetUpdate() {
statementFactory.setKeyspaceProvider((entity, tableName) -> CqlIdentifier.fromCql("ks_" + tableName));
Query query = Query.query(where("foo").is("bar"));
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz").set("boo", "baa"), personEntity);
assertThat(update.build(ParameterHandling.INLINE).getQuery())
.isEqualTo("UPDATE ks_person.person SET first_name='baz', boo='baa' WHERE foo='bar'");
}
@Test // DATACASS-656
void shouldCreateSetUpdateWithTtl() {
WriteOptions options = WriteOptions.builder().ttl(Duration.ofMinutes(1)).build();
Query query = Query.query(Criteria.where("foo").is("bar")).queryOptions(options);
Query query = Query.query(where("foo").is("bar")).queryOptions(options);
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz"), personEntity);
@@ -441,7 +508,7 @@ class StatementFactoryUnitTests {
void shouldCreateSetUpdateWithTimestamp() {
WriteOptions options = WriteOptions.builder().timestamp(1234).build();
Query query = Query.query(Criteria.where("foo").is("bar")).queryOptions(options);
Query query = Query.query(where("foo").is("bar")).queryOptions(options);
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz"), personEntity);
@@ -454,7 +521,7 @@ class StatementFactoryUnitTests {
void updateWithOptionsShouldRenderBindMarker() {
WriteOptions options = WriteOptions.builder().ttl(Duration.ofMinutes(1)).timestamp(1234).build();
Query query = Query.query(Criteria.where("foo").is("bar")).queryOptions(options);
Query query = Query.query(where("foo").is("bar")).queryOptions(options);
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz"), personEntity);
@@ -626,7 +693,7 @@ class StatementFactoryUnitTests {
@Test // DATACASS-569
void shouldCreateSetUpdateIfExists() {
Query query = Query.query(Criteria.where("foo").is("bar"))
Query query = Query.query(where("foo").is("bar"))
.queryOptions(UpdateOptions.builder().withIfExists().build());
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
@@ -639,8 +706,8 @@ class StatementFactoryUnitTests {
@Test // DATACASS-656
void shouldCreateSetUpdateIfCondition() {
Query query = Query.query(Criteria.where("foo").is("bar"))
.queryOptions(UpdateOptions.builder().ifCondition(Criteria.where("foo").is("baz")).build());
Query query = Query.query(where("foo").is("bar"))
.queryOptions(UpdateOptions.builder().ifCondition(where("foo").is("baz")).build());
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz"), personEntity);
@@ -657,7 +724,7 @@ class StatementFactoryUnitTests {
.serialConsistencyLevel(DefaultConsistencyLevel.QUORUM) //
.build();
Query query = Query.query(Criteria.where("foo").is("bar")).queryOptions(queryOptions);
Query query = Query.query(where("foo").is("bar")).queryOptions(queryOptions);
StatementBuilder<com.datastax.oss.driver.api.querybuilder.update.Update> update = statementFactory.update(query,
Update.empty().set("firstName", "baz"), personEntity);
@@ -698,7 +765,7 @@ class StatementFactoryUnitTests {
@Test // DATACASS-656
void shouldCreateSetUpdateFromObjectIfCondition() {
UpdateOptions options = UpdateOptions.builder().ifCondition(Criteria.where("foo").is("bar")).build();
UpdateOptions options = UpdateOptions.builder().ifCondition(where("foo").is("bar")).build();
Person person = new Person();
person.id = "foo";
person.firstName = "bar";
@@ -774,7 +841,7 @@ class StatementFactoryUnitTests {
@Test // DATACASS-512
void shouldCreateCountQuery() {
Query query = Query.query(Criteria.where("foo").is("bar"));
Query query = Query.query(where("foo").is("bar"));
StatementBuilder<Select> count = statementFactory.count(query,
converter.getMappingContext().getRequiredPersistentEntity(Group.class));