Introduzione a Spring Data Cassandra

1. Panoramica

Questo articolo è un'introduzione pratica al lavoro con Cassandra con Spring Data.

Inizieremo dalle basi e passeremo attraverso le configurazioni e la codifica, creando infine un modulo Spring Data Cassandra completo.

2. Dipendenze di Maven

Cominciamo definendo le dipendenze nel pom.xml , con Maven:

 com.datastax.cassandra cassandra-driver-core 2.1.9 

3. Configurazione per Cassandra

Useremo lo stile di configurazione Java in tutto questo per configurare l'integrazione di Cassandra.

3.1. La configurazione principale

Cominciamo con la classe di configurazione principale, ovviamente guidata tramite l' annotazione @Configuration a livello di classe :

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

Notare il nuovo bean - BasicCassandraMappingContext - con un'implementazione predefinita. Ciò è necessario per mappare le entità persistenti tra il loro oggetto e i loro formati persistenti.

E poiché l'implementazione predefinita è sufficientemente efficiente, possiamo usarla direttamente.

3.2. Proprietà di connessione Cassandra

Ci sono tre impostazioni obbligatorie che dobbiamo configurare per impostare la connessione per un client Cassandra.

Dobbiamo impostare il nome host che il server Cassandra esegue come c ontactPoints. La porta è semplicemente la porta di ascolto per la richiesta nel server. KeyspaceName è lo spazio dei nomi che definisce la replica dei dati sui nodi, che si basa su un concetto correlato a Cassandra.

4. Il Repository Cassandra

Utilizzeremo un CassandraRepository per il livello di accesso ai dati. Ciò segue l'astrazione del repository di Spring Data, che si concentra sull'astrazione del codice richiesto per implementare i livelli di accesso ai dati attraverso diversi meccanismi di persistenza.

4.1. Crea il CassandraRepository

Creiamo il CassandraRepository da utilizzare nella configurazione:

@Repository public interface BookRepository extends CassandraRepository { // }

4.2. Configurazione per CassandraRepository

Ora, possiamo estendere la configurazione nella sezione 3.1, aggiungendo l' annotazione a livello di classe @EnableCassandraRepositories per contrassegnare il nostro Cassandra Repository creato nella sezione 4.1 in CassandraConfig:

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

5. L'Entità

Diamo una rapida occhiata all'entità: la classe del modello che useremo. La classe è annotata e definisce parametri aggiuntivi per la creazione della tabella dati Cassandra dei metadati in modalità incorporata.

Utilizzando l' annotazione @Table , il bean viene mappato direttamente a una tabella di dati Cassandra. Inoltre ogni proprietà è definita come un tipo di chiave primaria o una semplice colonna:

@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. Test con un server incorporato

6.1. Dipendenze di Maven

Se si desidera eseguire Cassandra in modalità incorporata (senza installare manualmente un server Cassandra separato), è necessario aggiungere le dipendenze relative all'unità 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 

È possibile utilizzare un server Cassandra incorporato per testare questa applicazione . Il vantaggio principale è che non vuoi installare Cassandra in modo esplicito.

Questo server integrato è compatibile anche con i test Spring JUnit. Qui possiamo impostare SpringJUnit4ClassRunner utilizzando l' annotazione @RunWith insieme al server incorporato. Quindi è possibile implementare una suite di test completa senza avere un servizio Cassandra esterno in esecuzione.

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

6.2. Avvio e arresto del server

Puoi ignorare questa sezione se stai utilizzando un server Cassandra esterno.

Dobbiamo avviare il server una volta per l'intera suite di test, quindi il metodo di avvio del server è contrassegnato con l' annotazione @BeforeClass :

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

Successivamente dobbiamo assicurarci che il server sia arrestato dopo il completamento dell'esecuzione della suite di test:

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

6.3. Tabella dati pulita

È buona norma eliminare e creare la tabella dati prima di ogni esecuzione del test, per evitare risultati imprevisti dovuti ai dati manipolati nelle precedenti esecuzioni dei test.

Ora possiamo creare la tabella dati all'avvio del server:

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

e rilascia dopo ogni singola esecuzione del test case:

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

7. Accesso ai dati tramite CassandraRepository

Possiamo utilizzare direttamente il BookRepository che abbiamo creato sopra per persistere, manipolare e recuperare i dati nel database di Cassandra.

7.1. Salva un nuovo libro

Possiamo salvare un nuovo libro nel nostro book store:

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

Quindi possiamo verificare la disponibilità del libro inserito nel database:

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

7.2. Aggiorna un libro esistente

Inizio di Lat inserendo un nuovo libro:

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

Andiamo a prendere il libro dal titolo:

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

Quindi cambiamo il titolo del libro:

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

Infine controlliamo se il titolo è aggiornato nel database:

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

7.3. Elimina il libro esistente

Inserisci un nuovo libro:

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

Quindi elimina il libro appena inserito:

bookRepository.delete(javaBook); 

Ora possiamo verificare l'eliminazione:

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

Ciò causerà la generazione di un'eccezione NoSuchElementException dal codice assicurandosi che il libro venga eliminato.

7.4. Trova tutti i libri

Inserisci prima un nuovo libro:

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

Trova tutti i libri:

Iterable books = bookRepository.findAll();

Quindi possiamo controllare il numero di libri disponibili nel database:

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

8. Conclusione

Abbiamo seguito un'introduzione pratica di base a Cassandra con i dati di primavera utilizzando l'approccio più comune utilizzando il meccanismo di accesso ai dati di CassandraRepository .

L'implementazione dei frammenti di codice e degli esempi di cui sopra può essere trovata nel mio progetto GitHub: questo è un progetto basato su Eclipse, quindi dovrebbe essere facile da importare ed eseguire così com'è.