拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 在 Spring Data Cassandra 中保存日期值

在 Spring Data Cassandra 中保存日期值

白鹭 - 2021-11-18 2347 0 2

1. 概述

Apache Cassandra 是一个可扩展的 NoSQL 数据库。它提供了无单点故障的持续可用性。此外,Cassandra 能够以卓越的性能处理大量数据。


在本教程中,我们将了解使用 Spring Data 和 Docker 连接到 Cassandra。此外,我们将利用 Spring Data 存储库抽象来处理 Cassandra 的数据层。


我们将看到如何在 Cassandra 中保存不同的 Java 日期值。最后,我们将研究这些日期值如何映射到 Cassandra 类型。


2. Cassandra 的 Spring 数据

Spring Data for Apache Cassandra 为 Spring 开发人员提供了一个熟悉的界面来使用 Cassandra 。该项目将核心 Spring 概念应用于使用 Cassandra 数据存储的解决方案的开发。


Spring Data 允许我们基于常见的 Spring 接口创建存储库。它还允许使用QueryBuilders来消除学习 Cassandra 查询语言 (CQL) 的需要。该项目提供了支持丰富对象映射的简单注释。


有两个重要的辅助类:

  • CqlTemplate处理常见的数据访问操作

  • CassandraTemplate提供对象映射

该项目与 Spring 的核心 JDBC 支持有明显的相似之处。

3. 搭建测试环境

为了开始,我们需要建立一个到 Cassandra 实例的连接。


请注意,我们也可以连接到 Astra DB 数据库,这是一个基于 Apache Cassandra 的基于云的数据库。


本指南将向您展示如何连接到 Datastax Astra DB 。

3.1.卡桑德拉容器

Testcontainers库来配置和启动 Cassandra。首先,我们将定义一个 Cassandra 容器并将其暴露在特定端口上:

@Container
public static final CassandraContainer cassandra = (CassandraContainer) new CassandraContainer("cassandra:3.11.2")
.withExposedPorts(9042);

接下来,我们需要覆盖 Spring Data 所需的测试属性,以便能够与 Cassandra 容器建立连接:

TestPropertyValues.of( "spring.data.cassandra.keyspace-name=" + KEYSPACE_NAME, "spring.data.cassandra.contact-points=" + cassandra.getContainerIpAddress(), "spring.data.cassandra.port=" + cassandra.getMappedPort(9042)
).applyTo(configurableApplicationContext.getEnvironment());

最后,在创建任何对象/表之前,我们需要创建一个键空间:

session.execute("CREATE KEYSPACE IF NOT EXISTS " + KEYSPACE_NAME + " WITH replication = {'class':'SimpleStrategy','replication_factor':'1'};");

密钥空间只是 Cassandra 中的一个数据容器。实际上,它与 RDBMS 中的数据库非常相似。

3.2. Cassandra 存储库

Spring Data 的存储库支持大大简化了 DAO 的实现。让我们从创建一个简单的 DAO 开始。


org.springframework.data.cassandra.core.mapping包中提供的@Table注释启用域对象映射:

@Table
public class Person { @PrimaryKey
private UUID id; private String firstName; private String lastName; public Person(UUID id, String firstName, String lastName) { this.id = id; this.firstName = firstName; this.lastName = lastName;
} //getters, setters, equals and hash code

}

CassandraRepository接口为我们的 DAO 定义一个 Spring Data 存储库:

@Repository
public interface PersonRepository extends CassandraRepository<Person, UUID> {}

最后,在开始编写集成测试之前,我们需要定义两个额外的属性:

spring.data.cassandra.schema-action=create_if_not_exists
spring.data.cassandra.local-datacenter=datacenter1

第一个属性将确保 Spring Data 自动为我们创建带注释的表。


我们应该注意,不建议将此设置用于生产系统。


4. 使用日期值

在用于 Apache Cassandra 的 Spring Data 的现代版本中,处理日期值非常简单。 Spring Data 将自动确保 Java 日期类型与 Apache Cassandra 表示正确映射。

4.1.本地日期类型

让我们向Person DAO LocalDate类型的新字段birthDate

@Test
public void givenValidPersonUsingLocalDate_whenSavingIt_thenDataIsPersisted() {
UUID personId = UUIDs.timeBased();
Person newPerson = new Person(personId, "Luka", "Modric");
newPerson.setBirthDate(LocalDate.of(1985, 9, 9));
personRepository.save(newPerson);

List<Person> savedPersons = personRepository.findAllById(List.of(personId));
assertThat(savedPersons.get(0)).isEqualTo(newPerson);
}

Spring Data 自动将 Java 的LocalDate转换为 Cassandra 的date类型。从 Cassandra 保存和获取记录后,DAO 中的LocalDate

4.2.本地日期时间类型

让我们向Person DAO 添加另一个名为lastVisitedDate LocalDateTime类型的字段:

@Test
public void givenValidPersonUsingLocalDateTime_whenSavingIt_thenDataIsPersisted() {
UUID personId = UUIDs.timeBased();
Person newPerson = new Person(personId, "Luka", "Modric");
newPerson.setLastVisitedDate(LocalDateTime.of(2021, 7, 13, 11, 30));
personRepository.save(newPerson);

List<Person> savedPersons = personRepository.findAllById(List.of(personId));
assertThat(savedPersons.get(0)).isEqualTo(newPerson);
}

Spring Data 自动将 Java 的LocalDateTime转换为 Cassandra 的时间戳类型。从 Cassandra 保存和获取记录后,DAO 中的LocalDateTime

4.3.旧日期类型

最后,让我们将遗留类型Date 的**名为 lastPurchasedDate的字段添加到我们的Person DAO 中:

@Test
public void givenValidPersonUsingLegacyDate_whenSavingIt_thenDataIsPersisted() {
UUID personId = UUIDs.timeBased();
Person newPerson = new Person(personId, "Luka", "Modric");
newPerson.setLastPurchasedDate(new Date(LocalDate.of(2021, 7, 13).toEpochDay()));
personRepository.save(newPerson);

List<Person> savedPersons = personRepository.findAllById(List.of(personId));
assertThat(savedPersons.get(0)).isEqualTo(newPerson);
}

與LocalDateTime, Spring Data 將 Java 的java.util.Date轉換為 Cassandra 的時間戳類型。

4.4.映射的 Cassandra 类型

让我们使用 CQLSH 检查保存在 Cassandra 中的数据。它是一个命令行 shell,用于通过 CQL 与 Cassandra 进行交互。


为了在测试执行期间检查 Cassandra 容器中存储了哪些数据,我们可以简单地在我们的测试中放置一个断点。在暂停的测试执行期间,我们可以通过 Docker 桌面应用程序连接到 Docker 容器 CLI:

saving-date-values-in-spring-data-cassandra.png

连接到 Docker 容器 CLI 后,我们应该首先选择键空间,然后选择表:

# cqlsh
Connected to Test Cluster at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 3.11.2 | CQL spec 3.4.4 | Native protocol v4]
Use HELP for help.
cqlsh> USE test;
cqlsh:test> select * from person;

因此,CQLSH 将向我们显示保存在表中的数据的格式化输出:

 id | birthdate | firstname | lastname | lastpurchaseddate | lastvisiteddate
--------------------------------------+------------+-----------+----------+-------------------+-----------------
9abef910-e3fd-11eb-9829-c5149ac796de | 1985-09-09 | Luka | Modric | null | null

但是,我们还想检查用于特定日期列的数据类型:

cqlsh:test> DESC TABLE person;

输出返回用于创建表的 CQL 命令。因此,它包含所有数据类型定义:

CREATE TABLE test.person (
id uuid PRIMARY KEY,
birthdate date,
firstname text,
lastname text,
lastpurchaseddate timestamp,
lastvisiteddate timestamp
)

5. 结论

在本文中,我们探讨了如何在 Spring Data for Apache Cassandra 中使用不同的日期值。

在示例中,我们介绍了如何使用LocalDate 、 LocalDateTime,和遗留的Date Java 类型。我们看到了如何连接到使用Testcontainers开始的 Cassandra 实例。最后,我们使用 Spring Data 存储库抽象来操作存储在 Cassandra 中的数据。


标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *