1. 概述

这是 Spring Data Cassandra 系列文章的第二篇。本文将重点介绍数据访问层中 CassandraTemplate 和 CQL 查询的使用方式。如果你还没看过第一篇,建议先阅读 Spring Data Cassandra 入门指南

Cassandra Query Language (CQL) 是用于操作 Cassandra 数据库的查询语言,而 CqlTemplate 则是 Spring Data Cassandra 提供的低级数据访问模板,它封装了执行 CQL 语句所需的操作。

CassandraTemplate 构建在 CqlTemplate 之上,提供了一种更便捷的方式来操作领域对象,并将其映射为 Cassandra 中持久化的数据结构。

接下来我们会从配置开始,然后通过示例深入讲解这两个模板的用法。

2. CassandraTemplate 配置

由于我们的主配置类继承了 AbstractCassandraConfiguration,因此 CassandraTemplate 已经自动注册到 Spring 上下文中:

@Configuration
@EnableCassandraRepositories(basePackages = "com.baeldung.spring.data.cassandra.repository")
public class CassandraConfig extends AbstractCassandraConfiguration { ... }

我们可以直接注入这个模板 —— 可以按具体类型 CassandraTemplate 注入,也可以使用更通用的接口 CassandraOperations

@Autowired
private CassandraOperations cassandraTemplate;

3. 使用 CassandraTemplate 进行数据访问

我们将在数据访问层模块中使用上面定义的 CassandraTemplate 来处理数据持久化操作。

3.1. 插入一本新书

向书店插入一本新书:

Book javaBook = new Book(
  UUIDs.timeBased(), "Head First Java", "O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
cassandraTemplate.insert(javaBook);

然后检查数据库中是否成功插入:

Select select = QueryBuilder.select().from("book")
  .where(QueryBuilder.eq("title", "Head First Java"))
  .and(QueryBuilder.eq("publisher", "O'Reilly Media"));
Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);

这里使用的是 Select QueryBuilder,最终会映射到 cassandraTemplate.selectOne() 方法。QueryBuilder 的详细用法我们会在 CQL 查询部分进一步展开。

3.2. 批量插入书籍

可以通过一个列表批量插入多本书:

Book javaBook = new Book(
  UUIDs.timeBased(), "Head First Java", "O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
Book dPatternBook = new Book(
  UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
List<Book> bookList = new ArrayList<Book>();
bookList.add(javaBook);
bookList.add(dPatternBook);
cassandraTemplate.insert(bookList);

3.3. 更新已有书籍

首先插入一本书:

Book javaBook = new Book(
  UUIDs.timeBased(), "Head First Java", "O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
cassandraTemplate.insert(javaBook);

接着获取这本书:

Select select = QueryBuilder.select().from("book");
Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);

然后给这本书添加新的标签:

retrievedBook.setTags(ImmutableSet.of("Java", "Programming"));
cassandraTemplate.update(retrievedBook);

3.4. 删除指定书籍

插入一本书:

Book javaBook = new Book(
  UUIDs.timeBased(), "Head First Java", "O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
cassandraTemplate.insert(javaBook);

然后删除:

cassandraTemplate.delete(javaBook);

3.5. 清空所有书籍

先插入几本书:

Book javaBook = new Book(
  UUIDs.timeBased(), "Head First Java", "O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
Book dPatternBook = new Book(
  UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", 
  ImmutableSet.of("Computer", "Software"));
cassandraTemplate.insert(javaBook);
cassandraTemplate.insert(dPatternBook);

然后清空表:

cassandraTemplate.deleteAll(Book.class);

4. 使用 CQL 查询进行数据访问

在数据访问层中,我们也可以直接使用 CQL 查询来操作数据。CQL 查询由 CqlTemplate 类负责处理,允许我们按需执行自定义查询。

由于 CassandraTemplateCqlTemplate 的子类,所以我们可以直接使用它来执行这些查询。

下面来看几种常见的 CQL 查询操作方法。

4.1. 使用 QueryBuilder

QueryBuilder 可以帮助我们构建数据库中的各种查询语句。大部分标准操作都可以通过其内置的构建块来完成:

Insert insertQueryBuider = QueryBuilder.insertInto("book")
 .value("isbn", UUIDs.timeBased())
 .value("title", "Head First Java")
 .value("publisher", "OReilly Media")
 .value("tags", ImmutableSet.of("Software"));
cassandraTemplate.execute(insertQueryBuider);

注意这里使用的是 execute() 方法,而不是具体的 insert、delete 等方法。因为查询类型是由 QueryBuilder 构造出的对象决定的。

4.2. 使用 PreparedStatements

虽然 PreparedStatement 可以用于任何场景,但通常推荐在需要高速批量插入时使用。

PreparedStatement 只需预编译一次,性能表现更好:

UUID uuid = UUIDs.timeBased();
String insertPreparedCql = 
  "insert into book (isbn, title, publisher, tags) values (?, ?, ?, ?)";
List<Object> singleBookArgsList = new ArrayList<>();
List<List<?>> bookList = new ArrayList<>();
singleBookArgsList.add(uuid);
singleBookArgsList.add("Head First Java");
singleBookArgsList.add("OReilly Media");
singleBookArgsList.add(ImmutableSet.of("Software"));
bookList.add(singleBookArgsList);
cassandraTemplate.ingest(insertPreparedCql, bookList);

4.3. 使用原始 CQL 语句

当然你也可以直接写 CQL 语句来执行操作:

UUID uuid = UUIDs.timeBased();
String insertCql = "insert into book (isbn, title, publisher, tags) 
  values (" + uuid + ", 'Head First Java', 'OReilly Media', {'Software'})";
cassandraTemplate.execute(insertCql);

⚠️ 踩坑提醒:这种方式容易引发 SQL 注入问题,请务必谨慎使用!

5. 总结

在这篇文章中,我们探讨了多种使用 Spring Data Cassandra 操作数据的方式,包括 CassandraTemplate 和 CQL 查询。

✅ 示例代码可以在 GitHub 项目 中找到 —— 该项目基于 Maven 构建,导入即可运行,无需额外配置。


原始标题:Using Spring Data CassandraTemplate