We now drop Cassandra tables before dropping user types as user types cannot be removed when they are used in table definitions. Schema creation and schema drops are now split into two classes.
Reformat code. Add ticket references to test methods. Deprecate Comparator IT instances because of their unintuitive names and re-introduce it under INSTANCE.
We now compare persistent properties using their column names when both columns are regular columns. Column names either respect a defined column name or determine a column name based on the property name.
Previously, the comparison extracted the column name itself and in case the other column was not annotated, the column compared with itself, the column name with its own property name which breaks the comparator contract.
Improve documentation on CassandraTemplate. Explain differences between Spring CQL and Spring Data Cassandra. Add User-Defined-Type mapping example. Fix typos.
Align documentation structure with other Spring Data Modules. Add chapters for mapping and supported data types. Add new features chapter. Merge existing documentation into the aligned structure. Add John Blum and Mark Paluch to pom.xml.
We now support DTO projections for query methods. DTO projection selects records from Cassandra and applies projected results on the DTO. DTOs are plain Java objects that fit to the underlying entity.
@Table
class Person {
@PrimaryKeyColumn(type = PrimaryKeyType.PARTITIONED, ordinal = 0) private String lastname;
@PrimaryKeyColumn(type = PrimaryKeyType.CLUSTERED, ordinal = 1) private String firstname;
private String nickname;
private Date birthDate;
// more columns
}
interface PersonRepository extends CrudRepository<Person, String> {
Collection<PersonDto> findPersonDtoBy();
<T> T findDtoByFirstnameStartsWith(String prefix, Class<T> projectionType);
}
class PersonDto {
public String firstname, lastname;
public PersonDto(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
}
We no longer require entities to be annotated with @Table for data mapping and CRUD operations.
Entities without @Table can be still mapped in both directions and will be excluded from schema-management to prevent table creation for unwanted classes.
A class annotated with @Table will participate in schema management and be exposed as a table entity. Classes used as entities without @Table can still be used to query Cassandra but schema management will not create any tables for these classes.
@Table // entity qualified for schema management
class Person {
@Id private String id;
private String lastname;
private String firstname;
}
// entity that can be used for
// select/insert/update/delete operations and repository use
class Person {
@Id private String id;
private String lastname;
private String firstname;
}
Previously, query method parameter conversion was handled separately. This was duplicate code and the code additionally converted arguments into property types regardless the further usage. Collection arguments (e.g. for IN query usage) could be converted into the property type (List of String converted into String).
We now handle collection conversion and single element conversion separately so collections are no longer converted into the property's type. Collection elements are now inspected individually regarding their type/simple type conversion.
This change also considers enum types as simple types with a distinct conversion of the enum value into a Cassandra value (numeric, character). The change in enum value handling reduces the scope of the conversion service usage and prevents accidental conversion.
Original pull request: #89.
We now support @AliasFor to build composed annotations with @Table, @UserDefinedType, @PrimaryKey, @PrimaryKeyClass, @PrimaryKeyColumn, @Column, @Query, @CassandraType.
Original pull request: #90.
Revert added features in version 1.0 schema files in favor of version 1.5 schema files. Remove license header. Remove TODOs and fix documentation source names.
We now support Cassandra User-defined types. UDTs can be created using CQL generators and used inside of mapped domain classes. User-defined types can be used either raw as UDTValue that is passed through or as mapped object. Mapped UDTs must be annotated with @UserDefinedType. Types are included into schema generation so known and defined UDTs are created before any tables are created. UDTs can be used with set and list collection types and in primary keys. UDTs can also be used in repository query methods as query predicates.
Updating UDTs will update the whole UDT.
@UserDefinedType
public class Address {
String city;
String country;
}
@Table
public class Person {
@Id String id;
Address address;
UDTValue genericUdt;
}
The XML namespace support was extended with new schema versions to support provide a User Type resolver so UDTs can be resolved:
<cassandra:mapping>
<cassandra:user-type-resolver keyspace-name="${cassandra.keyspace}" />
</cassandra:mapping>
We now consider registered custom write converters for top-level collection types (like Map<String, Collection<String>>) to convert properties to Java types. Previously, only collection component types and non-collection top-level types were used to determine a converter.
Methods accepting a List of entities perform batching operations (insert/update/delete).
This can be fine for entities sharing a partition key but leads in most cases to distributed batches across a Cassandra cluster which is an anti-pattern. CassandraTemplate exposes CassandraBatchOperations for batching operations. As of Version 1.5, all methods accepting a List of entities are deprecated because there is no alternative of inserting multiple rows in an atomic way that guarantees not to harm Cassandra performance. These methods will be removed in Version 2.0.
We now support named and expression parameters in String-based repository query methods. Name-based parameters are referenced with :parameter. Expression parameters can reference either parameter names (if provided) with :#{expression}/#{#fieldname} or index-based with ?#{[0]}.
String-based query creation now also serializes parameters using the configured CodecRegistry so escaping and serialization is handled by the driver itself which leads to correct queries.
public interface SampleRepository extends Repository<Person, String> {
@Query("SELECT * FROM person WHERE lastname = ?0;")
Person findByLastname(String lastname);
@Query("SELECT * FROM person WHERE lastname = :lastname;")
Person findByNamedParameter(@Param("lastname") String lastname);
@Query("SELECT * FROM person WHERE lastname = ?#{[0]};")
Person findByIndexExpressionParameter(String lastname);
@Query("SELECT * FROM person WHERE lastnames IN (?0) AND age = ?1;")
Person findByLastNamesAndAge(Collection<String> lastname, int age);
@Query("SELECT * FROM person WHERE lastname = :#{#lastname == 'Matthews' ? 'Admin' : #lastname};")
Person findByConditionalExpressionParameter(@Param("lastname") String lastname);
}
Related tickets: DATACASS-122, DATACASS-240
We provide now two separate verifiers for Table types and PrimaryKey types. Exception messages are aligned between both verifiers and the checks use simplified code instead to perform checks. VerifierMappingExceptions introduces now immutability and methods introducing mutability are deprecated.
We now rely on Row.getObject(…) to retrieve data from a Cassandra Column. CodecRegistry and ProtocolVersion are configured on Cluster so there's no need to use a static configured CodecRegistry and ProtocolVersion that might not fit the configured values.
We now consider the ordering of clustered columns when creating a CreateTableSpecification for mapped classes without a primary key class. Previously, the ordering was dropped silently.
High client churn seems to affect Cassandra in a negative way (connection timeouts, driver considers hosts as down). Almost all integration tests bootstrap their own Cluster instance and dispose it once the tests has finished. Identify tests where reuse of a global Cluster instance provided by CassandraRule is possible and switch from context bootstrapping to reuse. This helps to prevent integration test failures.