Введение в Spring Data Cassandra

Введение в Spring Data Cassandra

1. обзор

Эта статья представляет собой практическое введение в работу с Cassandra с Spring Data.

Мы начнем с основ, пройдемся по конфигурациям и кодированию, и, наконец, создадим полный модуль Spring Data Cassandra.

2. Maven Зависимости

Начнем с определения зависимостей вpom.xml с помощью Maven:


    com.datastax.cassandra
    cassandra-driver-core
    2.1.9

3. Конфигурация для Кассандры

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

3.1. Основная конфигурация

Давайте начнем с основного класса конфигурации - конечно, управляемого через саннотацию уровня класса@Configuration :

@Configuration
public class CassandraConfig extends AbstractCassandraConfiguration {

    @Override
    protected String getKeyspaceName() {
        return "testKeySpace";
    }

    @Bean
    public CassandraClusterFactoryBean cluster() {
        CassandraClusterFactoryBean cluster =
          new CassandraClusterFactoryBean();
        cluster.setContactPoints("127.0.0.1");
        cluster.setPort(9142);
        return cluster;
    }

    @Bean
    public CassandraMappingContext cassandraMapping()
      throws ClassNotFoundException {
        return new BasicCassandraMappingContext();
    }
}

Обратите внимание на новый компонент -BasicCassandraMappingContext - с реализацией по умолчанию. Это необходимо для сопоставления постоянных объектов между их объектами и их постоянными форматами.

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

3.2. Свойства подключения Cassandra

Есть три обязательных параметра, которые мы должны настроить, чтобы настроить соединение для клиента Cassandra.

Мы должны настроить имя хоста, чтобы сервер Cassandra работал как contactPoints. Port, это просто порт для прослушивания запросов на сервере. KeyspaceName - это пространство имен, которое определяет репликацию данных на узлах, основанную на концепции, связанной с Cassandra.

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

Мы собираемся использоватьCassandraRepository для уровня доступа к данным. Это следует за абстракцией репозитория Spring Data, которая направлена ​​на абстрагирование кода, необходимого для реализации уровней доступа к данным через различные механизмы персистентности.

4.1. СоздайтеCassandraRepository

Давайте создадимCassandraRepository для использования в конфигурации:

@Repository
public interface BookRepository extends CassandraRepository {
    //
}

4.2. Конфигурация дляCassandraRepository

Теперь мы можем расширить конфигурацию в разделе 3.1, добавив аннотацию уровня класса@EnableCassandraRepositories, чтобы отметить наш репозиторий Cassandra, созданный в разделе 4.1 вCassandraConfig:.

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

5. Организация

Давайте быстро рассмотрим сущность - класс модели, который мы собираемся использовать. Класс аннотирован и определяет дополнительные параметры для создания таблицы данных метаданных Cassandra во встроенном режиме.

Используя аннотацию@Table, компонент напрямую отображается в таблицу данных Cassandra. Также каждое свойство определяется как тип первичного ключа или простой столбец:

@Table
public class Book {
    @PrimaryKeyColumn(
      name = "isbn",
      ordinal = 2,
      type = PrimaryKeyType.CLUSTERED,
      ordering = Ordering.DESCENDING)
    private UUID id;
    @PrimaryKeyColumn(
      name = "title", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
    private String title;
    @PrimaryKeyColumn(
      name = "publisher", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
    private String publisher;
    @Column
    private Set tags = new HashSet<>();
    // standard getters and setters
}

6. Тестирование со встроенным сервером

6.1. Maven Зависимости

Если вы хотите запустить Cassandra во встроенном режиме (без ручной установки отдельного сервера Cassandra), вам необходимо добавить зависимости, связанные сcassandra-unit, вpom.xml:


    org.cassandraunit
    cassandra-unit-spring
    2.1.9.2
    test
    
        
        org.cassandraunit
        cassandra-unit
        
    


    org.cassandraunit
    cassandra-unit-shaded
    2.1.9.2
    test


    org.hectorclient
    hector-core
    2.0-0

Можноuse an embedded Cassandra server to test this application. Главное преимущество состоит в том, что вы не хотите устанавливать Cassandra явно.

Этот встроенный сервер также совместим с тестами Spring JUnit. Здесь мы можем установитьSpringJUnit4ClassRunner, используя аннотацию@RunWith вместе со встроенным сервером. Таким образом, можно реализовать полный набор тестов без запуска внешней службы Cassandra.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CassandraConfig.class)
public class BookRepositoryIntegrationTest {
    //
}

6.2. Запуск и остановка сервера

Вы можете игнорировать этот раздел, если вы используете внешний сервер Cassandra.

Мы должны запустить сервер один раз для всего набора тестов, поэтому метод запуска сервера отмечен аннотацией@BeforeClass:

@BeforeClass
public static void startCassandraEmbedded() {
    EmbeddedCassandraServerHelper.startEmbeddedCassandra();
    Cluster cluster = Cluster.builder()
      .addContactPoints("127.0.0.1").withPort(9142).build();
    Session session = cluster.connect();
}

Далее мы должны убедиться, что сервер остановлен после завершения выполнения набора тестов:

@AfterClass
public static void stopCassandraEmbedded() {
    EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}

6.3. Таблица чистых данных

Хорошей практикой является удаление и создание таблицы данных перед каждым выполнением теста, чтобы избежать неожиданных результатов из-за манипулирования данными в предыдущих выполнениях теста.

Теперь мы можем создать таблицу данных при запуске сервера:

@Before
public void createTable() {
    adminTemplate.createTable(
      true, CqlIdentifier.cqlId(DATA_TABLE_NAME),
      Book.class, new HashMap());
}

и отбрасывать после каждого выполнения теста:

@After
public void dropTable() {
    adminTemplate.dropTable(CqlIdentifier.cqlId(DATA_TABLE_NAME));
}

7. Доступ к данным с использованиемCassandraRepository

Мы можем напрямую использоватьBookRepository, которые мы создали выше, для сохранения, обработки и извлечения данных из базы данных Cassandra.

7.1. Сохранить новую книгу

Мы можем сохранить новую книгу в нашем книжном магазине:

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

Затем мы можем проверить наличие вставленной книги в базе данных:

Iterable books = bookRepository.findByTitleAndPublisher(
  "Head First Java", "O'Reilly Media");
assertEquals(javaBook.getId(), books.iterator().next().getId());

7.2. Обновить существующую книгу

Начните с того, что вставьте новую книгу:

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

Выберем книгу по названию:

Iterable books = bookRepository.findByTitleAndPublisher(
  "Head First Java", "O'Reilly Media");

Тогда давайте изменим название книги:

javaBook.setTitle("Head First Java Second Edition");
bookRepository.save(ImmutableSet.of(javaBook));

Наконец, давайте проверим, обновляется ли заголовок в базе данных:

Iterable books = bookRepository.findByTitleAndPublisher(
  "Head First Java Second Edition", "O'Reilly Media");
assertEquals(
  javaBook.getTitle(), updateBooks.iterator().next().getTitle());

7.3. Удалить существующую книгу

Вставьте новую книгу:

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

Затем удалите вновь введенную книгу:

bookRepository.delete(javaBook);

Теперь мы можем проверить удаление:

Iterable books = bookRepository.findByTitleAndPublisher(
  "Head First Java", "O'Reilly Media");
assertNotEquals(javaBook.getId(), books.iterator().next().getId());

Это вызовет исключение NoSuchElementException из кода, обеспечивающего удаление книги.

7.4. Найти все книги

Сначала вставьте новые книги:

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"));
bookRepository.save(ImmutableSet.of(javaBook));
bookRepository.save(ImmutableSet.of(dPatternBook));

Найти все книги:

Iterable books = bookRepository.findAll();

Затем мы можем проверить количество доступных книг в базе данных:

int bookCount = 0;
for (Book book : books) bookCount++;
assertEquals(bookCount, 2);

8. Заключение

Мы прошли базовое практическое введение в Cassandra с данными Spring, используя наиболее распространенный подход с использованием механизма доступа к даннымCassandraRepository.

Реализация приведенных выше фрагментов кода и примеров можно найти вmy GitHub project - это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.