Spring Data for Apache Cassandra is now a core module maintained by the Spring Data team. Besides the change in primary ownership of development effort, the Ingalls release train ships with a series of noteworthy changes to the module itself.

We upgraded to the Datastax Java Driver 3.1 and so Spring Data for Apache Cassandra now supports Apache Cassandra 3.0 (1.2, 2.0, 2.1, 2.2 and 3.0, up to 3.9).

This release also ships with support for query derivation so that you do not necessarily have to use string queries but can derive an Apache Cassandra CQL query from the query method name:

public interface BasicUserRepository extends Repository<User, Long> { /** * Derived query method. * Creates {@code SELECT * FROM users WHERE username = ?0}. */ User findUserByUsername(String username); /** * Derived query method using SASI (SSTable Attached Secondary Index) * features through the {@code LIKE} keyword. * This query corresponds with * {@code SELECT * FROM users WHERE lastname LIKE '?0'}. * {@link User#lastname} is not part of the * primary key so it requires a secondary index. */ List<User> findUsersByLastnameStartsWith(String lastnamePrefix); }

You can find examples for query derivation for Spring Data for Apache Cassandra in our examples repository.

Query derivation supports all predicates provided by Apache Cassandra and ships with predicates for SASI (SSTable Attached Secondary Index) indexes. In this context, query derivation is in not opinionated about primary keys or columns with a secondary index. There is no support for AllowFiltering yet. Also, repository query methods also support Stream as a return type. Using a Stream does not preload the whole result set but iterates over the results as you pull on the stream.

To round things off, you can now use JSR-310 and ThreeTen back-port types as well as JodaTime types in your domain classes that were added as part of the Java 8 support story. JSR-310 types are converted to native Apache Cassandra data types. Refer to the revised reference documentation or our Java 8 examples for details.

public class Order { @Id String id; LocalDate orderDate; ZoneId zoneId; } public interface OrderRepository extends Repository<Order, String> { /** * Method parameters are converted according the registered * Converters into Cassandra types. */ @Query("SELECT * from pizza_orders WHERE orderdate = ?0 and zoneid = ?1 ALLOW FILTERING") Order findOrderByOrderDateAndZoneId(LocalDate orderDate, ZoneId zoneId); /** * String-based query using native data types. */ @Query("SELECT * from pizza_orders WHERE orderdate = ?0 and zoneid = ?1 ALLOW FILTERING") Order findOrderByDate(com.datastax.driver.core.LocalDate orderDate, String zoneId); /** * Streaming query. */ Stream<Order> findAll(); }

Data type support is configurable by registering custom conversions. For details on this, make sure you check out the examples dedicated to this on GitHub.

A last noteworthy feature is user-defined types (UDT). With Ingalls, you can now either use mapped user-defined types embedded in your domain classes or just use the native UDTValue type.

@Table public class Person { @Id int id; String firstname, lastname; Address current; List<Address> previous; @CassandraType(type = Name.UDT, userTypeName = "address") UDTValue alternative; } @UserDefinedType public class Address { String street, zip, city; }

Explicitly mapped iser-defined types map structured values to UDTValue under the coverts so thatyyou can keep working with a domain class while the mapping is handled by Spring Data for Apache Cassandra.

UDT values are stored in a row which makes mapped UDTs embedded objects. You can use UDTs as singular property or as part of a collection type. If you are using schema creation, then user-defined types are created in the data store on application startup. UDTs are value objects conceptually, which means that updates to UDT values (by saving a domain object) result in replacing the entire value.