我们将从基础开始,完成配置和编码,最后构建一个完整的Spring Data Cassandra模块。
1.概述
本文使用Spring Data访问与Cassandra的实用介绍。Cassandra是一个支持快速写入的NoSQL数据库,可以用作事件溯源的事件存储等。
2. Maven依赖
让我们首先使用Maven 定义pom.xml中的依赖项:
<dependency> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-core</artifactId> <version>2.1.9</version> </dependency>
|
3. Cassandra的配置
我们将在整个过程中使用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(); } }
|
注意新的bean - BasicCassandraMappingContext - 带有默认实现。这是在对象和持久格式之间映射持久性实体所必需的。由于默认实现足够,我们可以直接使用它。
3.2。Cassandra连接属性
我们必须配置三个必需的设置来设置Cassandra客户端的连接。
我们必须设置Cassandra服务器作为contactPoints运行的主机名。端口只是服务器中请求的侦听端口。KeyspaceName是定义节点上数据复制的命名空间,它基于Cassandra相关概念。
4. Cassandra存储库
我们将使用CassandraRepository作为数据访问层。这遵循Spring Data存储库抽象,该抽象集中于抽象出跨不同持久性机制实现数据访问层所需的代码。
4.1。创建CassandraRepository
让我们创建要在配置中使用的CassandraRepository:
@Repository public interface BookRepository extends CassandraRepository<Book> { // }
|
4.2。CassandraRepository的配置
现在,我们可以扩展第3.1节中的配置,添加@EnableCassandraRepositories类级别注释来标记我们在CassandraConfig的 4.1节中创建的Cassandra存储库:@Configuration @EnableCassandraRepositories( basePackages = "org.baeldung.spring.data.cassandra.repository") public class CassandraConfig extends AbstractCassandraConfiguration { // }
|
5.实体
让我们快速浏览一下实体 - 我们将要使用的模型类。该类已注释,并为嵌入模式下的元数据Cassandra数据表创建定义了其他参数。使用@Table注释,bean直接映射到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<String> tags = new HashSet<>(); // standard getters and setters }
|
6.使用嵌入式服务器进行测试
6.1。Maven依赖
如果要在嵌入模式下运行Cassandra(无需手动安装单独的Cassandra服务器),则需要将与cassandra-unit相关的依赖项添加到pom.xml:<dependency> <groupId>org.cassandraunit</groupId> <artifactId>cassandra-unit-spring</artifactId> <version>2.1.9.2</version> <scope>test</scope> <exclusions> <exclusion> <groupId>org.cassandraunit</groupId> <artifactId>cassandra-unit</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.cassandraunit</groupId> <artifactId>cassandra-unit-shaded</artifactId> <version>2.1.9.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hectorclient</groupId> <artifactId>hector-core</artifactId> <version>2.0-0</version> </dependency>
|
可以使用嵌入式Cassandra服务器来测试此应用程序。主要优点是您不希望显式安装Cassandra。此嵌入式服务器也与Spring JUnit Tests兼容。在这里,我们可以使用@RunWith注释和嵌入式服务器设置SpringJUnit4ClassRunner。因此,可以在不运行外部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<String, Object>()); }
|
在每个测试用例执行后删除:@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<Book> books = bookRepository.findByTitleAndPublisher( "Head First Java", "O'Reilly Media"); assertEquals(javaBook.getId(), books.iterator().next().getId());
|
7.2。更新现有图书
Lat首先插入一本新书:Book javaBook = new Book( UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software")); bookRepository.save(ImmutableSet.of(javaBook));
|
让我们按标题取书:Iterable<Book> books = bookRepository.findByTitleAndPublisher( "Head First Java", "O'Reilly Media");
|
然后让我们改变这本书的标题:javaBook.setTitle("Head First Java Second Edition"); bookRepository.save(ImmutableSet.of(javaBook));
|
最后让我们检查标题是否在数据库中更新:Iterable<Book> 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<Book> 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<Book> books = bookRepository.findAll();
|
然后我们可以查看数据库中可用书籍的数量:int bookCount = 0; for (Book book : books) bookCount++; assertEquals(bookCount, 2);
|
8.结论
我们使用最常用的CassandraRepository数据访问机制,使用Spring数据对Cassandra进行了基本的动手介绍。
上面的代码片段和示例的实现可以在我的GitHub项目中中找到- 这是一个基于Eclipse的项目,因此它应该很容易导入和运行。