Перейти к основному содержимому

Сохранение значений даты в Spring Data Cassandra

· 6 мин. чтения

1. Обзор

Apache Cassandra — это масштабируемая база данных NoSQL. Он обеспечивает постоянную доступность без единой точки отказа . Кроме того, Cassandra способна обрабатывать большие объемы данных с исключительной производительностью.

В этом руководстве мы рассмотрим подключение к Cassandra с использованием Spring Data и Docker. Кроме того, мы будем использовать абстракцию репозитория Spring Data для работы со слоем данных Cassandra.

Мы увидим, как сохранить различные значения даты Java в Cassandra. Наконец, мы исследуем, как эти значения даты сопоставляются с типами Cassandra.

2. Весенние данные для Кассандры

Spring Data for Apache Cassandra предлагает разработчикам Spring знакомый интерфейс для работы с Cassandra . Этот проект применяет основные концепции Spring к разработке решений с использованием хранилища данных Cassandra.

Spring Data позволяет нам создавать репозитории на основе распространенных интерфейсов Spring. Это также позволяет использовать QueryBuilders , чтобы исключить необходимость изучения языка запросов Cassandra (CQL). Проект предоставляет простые аннотации, которые позволяют использовать расширенное сопоставление объектов.

Есть два важных вспомогательных класса:

  • CqlTemplate обрабатывает общие операции доступа к данным .
  • CassandraTemplate обеспечивает сопоставление объектов

Проект имеет заметное сходство с основной поддержкой JDBC в Spring.

3. Настройка тестовой среды

Чтобы начать работу, нам нужно настроить подключение к экземпляру Cassandra.

Обратите внимание, что вместо этого мы также можем подключиться к базе данных Astra DB, которая представляет собой облачную базу данных, построенную на Apache Cassandra.

В этом руководстве показано, как подключиться к базе данных Datastax Astra DB .

3.1. Кассандра Контейнер

Настроим и запустим Cassandra с помощью библиотеки Testcontainers . Для начала мы определим контейнер 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. По сути, это очень похоже на базу данных в СУБД.

3.2. Репозиторий Кассандры

Поддержка репозитория Spring Data значительно упрощает реализацию DAO . Начнем с создания простого DAO.

Аннотация @Table , представленная в пакете org.springframework.data.cassandra.core.mapping , позволяет отображать объекты домена:

@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

}

Далее мы определим репозиторий Spring Data для нашего DAO, расширив интерфейс CassandraRepository :

@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. Использование значений даты

В современных версиях Spring Data для Apache Cassandra работа со значениями даты довольно проста. Spring Data автоматически обеспечит правильное сопоставление типов дат Java с представлением Apache Cassandra и из него.

4.1. Тип локальной даты

Давайте добавим в наш Person DAO новое поле BirthdayDate типа LocalDate : ``

@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 автоматически преобразует LocalDate Java в тип даты Cassandra . Значение LocalDate в DAO идентично после сохранения и извлечения записи из Cassandra.

4.2. Тип LocalDateTime

Давайте добавим еще одно поле с именем lastVisitedDate типа LocalDateTime в наш DAO Person :

@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 автоматически преобразует LocalDateTime Java в тип временной метки Cassandra . Значение LocalDateTime в DAO идентично после сохранения и извлечения записи из Cassandra.

4.3. Устаревший тип даты

Наконец, давайте добавим поле lastPurchasedDate устаревшего типа Date в наш DAO Person :

@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

Давайте проверим данные, которые были сохранены в Cassandra, с помощью CQLSH. Это оболочка командной строки для взаимодействия с Cassandra через CQL.

Чтобы проверить, какие данные были сохранены в контейнере Cassandra во время выполнения теста, мы можем просто поставить точку останова в нашем тесте. Во время приостановленного выполнения теста мы можем затем подключиться к CLI контейнера Docker через приложение Docker Desktop:

./18df3b9ff1b4bb9e3fb09db54dafa3ae.png

После подключения к CLI контейнера Docker мы должны сначала выбрать пространство ключей, а затем таблицу:

# 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 для Apache Cassandra.

В примерах мы рассмотрели работу с LocalDate , LocalDateTime и устаревшим типом Date Java. Мы увидели, как подключение к экземпляру Cassandra началось с помощью Testcontainers . Наконец, мы использовали абстракцию репозитория Spring Data для управления данными, хранящимися в Cassandra.

Как всегда, исходный код доступен на GitHub .