Spring Data Cassandra lets a Spring application persist objects in Cassandra through repository interfaces. It also provides annotations that map Java classes to Cassandra tables. The repository pattern resembles Spring Data JPA, but Cassandra is not a relational database, so changing the dependency alone is not enough. section 4.1
To set up a nonreactive application:
- Add spring-boot-starter-data-cassandra instead of the Spring Data JPA or JDBC starter, and remove relational database dependencies. Its presence triggers repository autoconfiguration. section 4.1.1
- Connect to a Cassandra cluster. For development, a single node can run in Docker with port 9042 exposed. section 4.1.1
- Create a keyspace—the grouping of tables the repositories will use—and configure its name under spring.data.cassandra.keyspace-name. Configure the local datacenter as needed. section 4.1.1
package tacos;
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
import org.springframework.data.cassandra.core.mapping.Table;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
@Table("ingredients")
public class Ingredient {
@PrimaryKey
private String id;
private String name;
private Type type;
public enum Type {
WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
}
}
The Ingredient mapping is the simplest starting point: @Table names the Cassandra table, while @PrimaryKey marks the property identifying a row. These replace the JPA annotations used for relational persistence. section 4.1.3
More involved mappings reflect how Cassandra stores data. A taco can use a UUID partition key marked with @PrimaryKeyColumn(type=PrimaryKeyType.PARTITIONED); the partition key determines where its row is written. Related data can be copied into user-defined types rather than retrieved through foreign keys and joins. section 4.1.3
Figure 4.1 Instead of using foreign keys and joins, Cassandra tables are denormalized, with user-defined types containing data copied from related tables.
The diagram shows why mapping related objects takes more than swapping annotations: denormalized Cassandra tables can contain copies of data from related tables. section 4.1.3
package tacos.data;
import java.util.UUID;
import org.springframework.data.repository.CrudRepository;
import tacos.TacoOrder;
public interface OrderRepository
extends CrudRepository<TacoOrder, UUID> {
}
Once the domain type is mapped, a repository can extend CrudRepository with that type and its key type. Here, orders use UUID keys; an ingredient repository instead uses String keys. section 4.1.4
These examples use the nonreactive starter. Reactive persistence is a separate option, with a similar reactive repository programming model to Spring Data MongoDB. section 4.1.1 section 13.4
