Introduction à Spring Data Cassandra

1. Vue d'ensemble

Cet article est une introduction pratique à l'utilisation de Cassandra avec Spring Data.

Nous allons commencer par les bases et passer en revue les configurations et le codage, pour enfin construire un module complet Spring Data Cassandra.

2. Dépendances de Maven

Commençons par définir les dépendances dans le pom.xml , avec Maven:

 com.datastax.cassandra cassandra-driver-core 2.1.9 

3. Configuration pour Cassandra

Nous utiliserons le style de configuration Java tout au long de tout cela pour configurer l'intégration Cassandra.

3.1. La configuration principale

Commençons par la classe de configuration principale - bien sûr pilotée via l' annotation de niveau de classe @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(); } }

Notez le nouveau bean - BasicCassandraMappingContext - avec une implémentation par défaut. Cela est nécessaire pour mapper les entités persistantes entre leur objet et leurs formats persistants.

Et comme l'implémentation par défaut est suffisamment capable, nous pouvons l'utiliser directement.

3.2. Propriétés de connexion Cassandra

Il y a trois paramètres obligatoires que nous devons configurer pour configurer la connexion pour un client Cassandra.

Nous devons configurer le nom d'hôte que le serveur Cassandra exécute en tant que c ontactPoints. Le port est simplement le port d'écoute pour la demande dans le serveur. KeyspaceName est l'espace de noms qui définit la réplication des données sur les nœuds, qui est basée sur un concept lié à Cassandra.

4. Le référentiel Cassandra

Nous allons utiliser un CassandraRepository pour la couche d'accès aux données. Cela fait suite à l'abstraction du référentiel Spring Data, qui se concentre sur l'abstraction du code requis pour implémenter les couches d'accès aux données à travers différents mécanismes de persistance.

4.1. Créer le CassandraRepository

Créons le CassandraRepository à utiliser dans la configuration:

@Repository public interface BookRepository extends CassandraRepository { // }

4.2. Configuration pour CassandraRepository

Maintenant, nous pouvons étendre la configuration dans la section 3.1, en ajoutant l' annotation au niveau de la classe @EnableCassandraRepositories pour marquer notre référentiel Cassandra créé à la section 4.1 dans CassandraConfig:

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

5. L'entité

Jetons un coup d'œil à l'entité - la classe de modèle que nous allons utiliser. La classe est annotée et définit des paramètres supplémentaires pour la création de la table de données Cassandra de métadonnées en mode intégré.

À l' aide de l' annotation @Table , le bean est directement mappé à une table de données Cassandra. De plus, chaque propriété est définie comme un type de clé primaire ou une simple colonne:

@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 avec un serveur intégré

6.1. Dépendances de Maven

Si vous souhaitez exécuter Cassandra en mode intégré (sans installer manuellement un serveur Cassandra séparé), vous devez ajouter les dépendances liées à l' unité cassandra au 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 

Il est possible d' utiliser un serveur Cassandra intégré pour tester cette application . Le principal avantage est que vous ne souhaitez pas installer Cassandra explicitement.

Ce serveur intégré est également compatible avec les tests Spring JUnit. Ici, nous pouvons définir SpringJUnit4ClassRunner à l' aide de l' annotation @RunWith avec le serveur intégré. Il est donc possible d'implémenter une suite de tests complète sans faire fonctionner un service Cassandra externe.

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

6.2. Démarrage et arrêt du serveur

Vous pouvez ignorer cette section si vous exécutez un serveur Cassandra externe.

Nous devons démarrer le serveur une fois pour toute la suite de tests, donc la méthode de démarrage du serveur est marquée avec l' annotation @BeforeClass :

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

Ensuite, nous devons nous assurer que le serveur est arrêté après la fin de l'exécution de la suite de tests:

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

6.3. Nettoyer la table de données

Il est recommandé de supprimer et de créer la table de données avant chaque exécution de test, pour éviter des résultats inattendus dus aux données manipulées lors d'exécutions de test antérieures.

Maintenant, nous pouvons créer la table de données au démarrage du serveur:

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

et abandonner après chaque exécution de scénario de test:

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

7. Accès aux données à l'aide de CassandraRepository

Nous pouvons directement utiliser le BookRepository que nous avons créé ci-dessus pour conserver, manipuler et récupérer les données dans la base de données Cassandra.

7.1. Enregistrer un nouveau livre

Nous pouvons enregistrer un nouveau livre dans notre librairie:

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

Ensuite, nous pouvons vérifier la disponibilité du livre inséré dans la base de données:

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

7.2. Mettre à jour un livre existant

Lat commence par insérer un nouveau livre:

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

Allons chercher le livre par le titre:

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

Puis changeons le titre du livre:

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

Enfin vérifions si le titre est mis à jour dans la base de données:

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

7.3. Supprimer le livre existant

Insérez un nouveau livre:

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

Puis supprimez le livre nouvellement entré:

bookRepository.delete(javaBook); 

Nous pouvons maintenant vérifier la suppression:

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

Cela entraînera la levée d'une NoSuchElementException à partir du code en s'assurant que le livre est supprimé.

7.4. Trouver tous les livres

Insérez d'abord un nouveau livre:

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

Trouver tous les livres:

Iterable books = bookRepository.findAll();

Ensuite, nous pouvons vérifier le nombre de livres disponibles dans la base de données:

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

8. Conclusion

Nous sommes passés par une introduction pratique de base à Cassandra avec les données Spring en utilisant l'approche la plus courante utilisant le mécanisme d'accès aux données CassandraRepository .

L'implémentation des extraits de code et des exemples ci-dessus peut être trouvée dans mon projet GitHub - il s'agit d'un projet basé sur Eclipse, il devrait donc être facile à importer et à exécuter tel quel.