We now skip properties during mapping (assign a null value) if the backing result (Row, UDT) does not contain a particular column.
Resultsets with limited columns are common for projections, in interface projections we use the actual entity to back calls to the projection.
We now support Optimistic Locking for insert, update and delete operations leveraging Cassandra's lightweight transaction support. Modifying statements are enhanced with IF conditions to conditionally insert and modify rows and to prevent concurrent modifications by throwing OptimisticLockingFailureException.
@Table
class Person {
@Id String id;
String firstname;
String lastname;
@Version Long version;
}
Person daenerys = template.insert(new Person("Daenerys"));
Person tmp = template.findOne(query(where("id").is(daenerys.getId())), Person.class);
daenerys.setLastname("Targaryen");
template.save(daenerys);
template.save(tmp); // throws OptimisticLockingFailureException
We promote the usage of reified Kotlin API usage (myMethod<Person>() instead of myMethod(Person::class)) to facilitate a single and more idiomatic approach to Kotlin API usage.
Extension methods accepting KClass are deprecated now.
We now support conditions in lightweight transactions for UPDATE and DELETE statements. Conditions are Filter objects similar to the WHERE clause. Conditions are supported for entity and query-based update/delete methods.
UpdateOptions options = UpdateOptions.builder().ifCondition(where("firstname").is("Walter")).build();
User user = new User("heisenberg", "Walter", "White");
template.update(user, options);
DeleteOptions options = DeleteOptions.builder().ifCondition(where("counter").is(42)).build();
Query query = Query.query(where("id").is("heisenberg")).queryOptions(options);
template.delete(query, User.class);
BasicCassandraPersistentEntity.doWithAssociations(…) now no longer throws UnsupportedCassandraOperationException when trying to traverse associations. Calling doWithAssociations results in a no-op as there are no associations.
Related ticket: DATAREST-1337.
This commit introduces Coroutines support for ReactiveFluentCassandraOperations API via Kotlin extensions that provide suspendable functions prefixed by `await` or suffixed by `AndAwait` for Mono based APIs.
Extensions for Flux will be added when Kotlin/kotlinx.coroutines#254 is fixed.
We now support derived queries using the Between keyword. Between query parts map to either two simple parameters (findByAgeBetween(int from, int to)) or a Range<T> parameter that defines inclusive/exclusive boundary comparison (findByAgeBetween(Range<Integer> age)).
Between queries use are issued by default as exclusive ranges so findByAgeBetween(int from, int to) maps to age > from AND age < to.
Guava has removed Futures#transform method without the Executor parameter in version 26.0-jre
DefaultBridgeReactiveSession fails with NoSuchMethod exception when used with Guava 26.0-jre+.
Original pull request: #137.
We now support read-only properties by annotating such properties with @ReadOnlyProperty. Read-only properties are read from results but never written (i.e. through INSERT or UPDATE) back to Cassandra.
Read-only properties can still be updated by using the Update/Query API.
class Person {
@Id String id;
String firstname;
String lastname;
@ReadOnlyProperty String externallyUpdatedProperty;
}
CassandraTemplate template = …
Person person = …
template.insert(person);
We now limit the selected fields when using projections in repository query methods and by using query operations. Queries that return either a closed interface projection or DTO projection are inspected for the select fields and only these fields are included in the SELECT list.
CassandraBatchOperations.delete(…) and ReactiveCassandraBatchOperations.delete(…) methods now accept WriteOptions and subclasses (such as DeleteOptions) to adjust delete behavior.
Related ticket: DATACASS-606.
We now support lightweight transactions for entity deletion through DeleteOptions.
User user = …
DeleteOptions options = DeleteOptions.builder().withIfExists().build();
boolean applied = template.delete(user, options);