Introducción a Spring Data Cassandra

1. Información general

Este artículo es una introducción práctica para trabajar con Cassandra con Spring Data.

Comenzaremos desde lo básico y revisaremos las configuraciones y la codificación, finalmente construiremos un módulo completo de Spring Data Cassandra.

2. Dependencias de Maven

Comencemos por definir las dependencias en pom.xml , con Maven:

 com.datastax.cassandra cassandra-driver-core 2.1.9 

3. Configuración para Cassandra

Usaremos el estilo de configuración de Java a lo largo de todo esto para configurar la integración de Cassandra.

3.1. La configuración principal

Comencemos con la clase de configuración principal, por supuesto impulsada a través de la anotación @Configuration de nivel de clase :

@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(); } }

Observe el nuevo bean, BasicCassandraMappingContext , con una implementación predeterminada. Esto es necesario para mapear las entidades persistentes entre su objeto y sus formatos persistentes.

Y como la implementación predeterminada es lo suficientemente capaz, podemos usarla directamente.

3.2. Propiedades de conexión de Cassandra

Hay tres configuraciones obligatorias que tenemos que configurar para configurar la conexión para un cliente Cassandra.

Tenemos que configurar el nombre de host que ejecuta el servidor Cassandra como c ontactPoints. El puerto es simplemente el puerto de escucha para la solicitud en el servidor. KeyspaceName es el espacio de nombres que define la replicación de datos en los nodos, que se basa en un concepto relacionado con Cassandra.

4. El repositorio de Cassandra

Vamos a utilizar un CassandraRepository para la capa de acceso a datos. Esto sigue a la abstracción del repositorio de Spring Data, que se centra en abstraer el código necesario para implementar las capas de acceso a datos a través de diferentes mecanismos de persistencia.

4.1. Crear el repositorio Cassandra

Creemos el CassandraRepository para usar en la configuración:

@Repository public interface BookRepository extends CassandraRepository { // }

4.2. Configuración para CassandraRepository

Ahora, podemos extender la configuración en la Sección 3.1, agregando la anotación de nivel de clase @EnableCassandraRepositories para marcar nuestro Repositorio Cassandra creado en la sección 4.1 en CassandraConfig:

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

5. La entidad

Echemos un vistazo rápido a la entidad, la clase modelo que vamos a utilizar. La clase está anotada y define parámetros adicionales para la creación de la tabla de datos de Cassandra de metadatos en modo incrustado.

Con la anotación @Table , el bean se asigna directamente a una tabla de datos de Cassandra. Además, cada propiedad se define como un tipo de clave primaria o una columna simple:

@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. Prueba con un servidor integrado

6.1. Dependencias de Maven

Si desea ejecutar Cassandra en modo incrustado (sin instalar manualmente un servidor Cassandra separado), debe agregar las dependencias relacionadas con la unidad cassandra al 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 

Es posible utilizar un servidor Cassandra integrado para probar esta aplicación . La principal ventaja es que no desea instalar Cassandra explícitamente.

Este servidor integrado también es compatible con Spring JUnit Tests. Aquí podemos configurar SpringJUnit4ClassRunner usando la anotación @RunWith junto con el servidor integrado. Por lo tanto, es posible implementar un conjunto de pruebas completo sin tener un servicio Cassandra externo en ejecución.

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

6.2. Iniciar y detener el servidor

Puede ignorar esta sección si está ejecutando un servidor Cassandra externo.

Tenemos que iniciar el servidor una vez para todo el conjunto de pruebas, por lo que el método de inicio del servidor está marcado con la anotación @BeforeClass :

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

A continuación, debemos asegurarnos de que el servidor se detenga después de completar la ejecución de la suite de pruebas:

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

6.3. Tabla de datos limpia

Es una buena práctica eliminar y crear la tabla de datos antes de cada ejecución de prueba, para evitar resultados inesperados debido a los datos manipulados en ejecuciones de prueba anteriores.

Ahora podemos crear la tabla de datos cuando se inicia el servidor:

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

y caer después de cada ejecución de un caso de prueba:

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

7. Acceso a datos mediante CassandraRepository

Podemos usar directamente el BookRepository que creamos anteriormente para conservar, manipular y recuperar los datos en la base de datos de Cassandra.

7.1. Guardar un libro nuevo

Podemos guardar un libro nuevo en nuestra librería:

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

Luego podemos verificar la disponibilidad del libro insertado en la base de datos:

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

7.2. Actualizar un libro existente

Lat comienza insertando un nuevo libro:

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

Busquemos el libro por el título:

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

Entonces cambiemos el título del libro:

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

Finalmente, verifiquemos si el título está actualizado en la base de datos:

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

7.3. Eliminar el libro existente

Insertar un libro nuevo:

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

Luego elimine el libro recién ingresado:

bookRepository.delete(javaBook); 

Ahora podemos verificar la eliminación:

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

Esto hará que se genere una NoSuchElementException desde el código, asegurándose de que se elimine el libro.

7.4. Buscar todos los libros

Inserte un libro nuevo primero:

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));

Encuentra todos los libros:

Iterable books = bookRepository.findAll();

Luego podemos verificar la cantidad de libros disponibles en la base de datos:

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

8. Conclusión

Realizamos una introducción práctica básica a los datos de Cassandra con Spring utilizando el enfoque más común utilizando el mecanismo de acceso a datos de CassandraRepository .

La implementación de los fragmentos de código y ejemplos anteriores se puede encontrar en mi proyecto de GitHub; este es un proyecto basado en Eclipse, por lo que debería ser fácil de importar y ejecutar tal como está.