├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── example
│ │ ├── CassandraConfiguration.java
│ │ └── domain
│ │ ├── Event.java
│ │ └── EventRepository.java
└── resources
│ ├── cassandra.properties
│ └── logback.xml
└── test
└── java
└── example
├── BaseIntegrationTest.java
├── CassandraTemplateIntegrationTest.java
├── CqlTemplateIntegrationTest.java
└── EventRepositoryIntegrationTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Eclipse (we include .project etc as we will want these for installation of labs)
2 | .metadata
3 | bin/
4 | tmp/
5 | target/
6 | *.tmp
7 | *.bak
8 | *.swp
9 | *~.nib
10 | local.properties
11 |
12 | # External tool builders
13 | .externalToolBuilders/
14 |
15 | # Locally stored "Eclipse launch configurations"
16 | *.launch
17 |
18 | ## IntelliJ
19 | *.iml
20 | *.ipr
21 | *.iws
22 | .idea/
23 | out/
24 | target/
25 |
26 | # Folder config file
27 | Desktop.ini
28 |
29 | ## Mac
30 | .DS_Store
31 |
32 | # Eclipse Project artifacts
33 | .classpath
34 | .settings
35 | .project
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 OpenCredo Ltd
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | spring-data-cassandra-example
2 | =============================
3 | This repository contains the source code for [Spring Data Cassandra Overview](http://www.opencredo.com/spring-data-cassandra-overview/) article published on [OpenCredo](http://www.opencredo.com/) blog.
4 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | example
8 | spring-data-cassandra-example
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 |
14 | org.apache.maven.plugins
15 | maven-compiler-plugin
16 | 3.5.1
17 |
18 | 1.7
19 | 1.7
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | org.springframework.data
28 | spring-data-cassandra
29 | 1.1.0.RELEASE
30 |
31 |
32 | ch.qos.logback
33 | logback-classic
34 | 1.1.2
35 |
36 |
37 | junit
38 | junit
39 | 4.11
40 | test
41 |
42 |
43 | org.springframework
44 | spring-test
45 | 4.0.7.RELEASE
46 | test
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/main/java/example/CassandraConfiguration.java:
--------------------------------------------------------------------------------
1 | package example;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 | import org.springframework.context.annotation.PropertySource;
9 | import org.springframework.core.env.Environment;
10 | import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
11 | import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
12 | import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
13 | import org.springframework.data.cassandra.mapping.CassandraMappingContext;
14 | import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
15 |
16 | @Configuration
17 | @PropertySource(value = { "classpath:cassandra.properties" })
18 | @EnableCassandraRepositories(basePackages = { "example" })
19 | public class CassandraConfiguration extends AbstractCassandraConfiguration {
20 |
21 | private static final Logger LOG = LoggerFactory.getLogger(CassandraConfiguration.class);
22 |
23 | @Autowired
24 | private Environment environment;
25 |
26 | @Bean
27 | public CassandraClusterFactoryBean cluster() {
28 | CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
29 | cluster.setContactPoints(environment.getProperty("cassandra.contactpoints"));
30 | cluster.setPort(Integer.parseInt(environment.getProperty("cassandra.port")));
31 | return cluster;
32 | }
33 |
34 | @Override
35 | protected String getKeyspaceName() {
36 | return environment.getProperty("cassandra.keyspace");
37 | }
38 |
39 | @Bean
40 | public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
41 | return new BasicCassandraMappingContext();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/example/domain/Event.java:
--------------------------------------------------------------------------------
1 | package example.domain;
2 |
3 | import org.springframework.cassandra.core.Ordering;
4 | import org.springframework.cassandra.core.PrimaryKeyType;
5 | import org.springframework.data.cassandra.mapping.Column;
6 | import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
7 | import org.springframework.data.cassandra.mapping.Table;
8 |
9 | import java.util.HashSet;
10 | import java.util.Set;
11 | import java.util.UUID;
12 |
13 | @Table
14 | public class Event {
15 |
16 | @PrimaryKeyColumn(name = "id", ordinal = 2, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING)
17 | private final UUID id;
18 |
19 | @PrimaryKeyColumn(name = "type", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
20 | private final String type;
21 |
22 | @PrimaryKeyColumn(name = "bucket", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
23 | private final String bucket;
24 |
25 | @Column
26 | private final Set tags = new HashSet<>();
27 |
28 | public Event(UUID id, String type, String bucket, Set tags) {
29 | this.id = id;
30 | this.type = type;
31 | this.bucket = bucket;
32 | this.tags.addAll(tags);
33 | }
34 |
35 | public UUID getId() {
36 | return id;
37 | }
38 |
39 | public String getType() {
40 | return type;
41 | }
42 |
43 | public String getBucket() {
44 | return bucket;
45 | }
46 |
47 | public Set getTags() {
48 | return tags;
49 | }
50 |
51 | @Override
52 | public String toString() {
53 | return "Event{" + "id=" + id + ", type=" + type + ", bucket=" + bucket + ", tags=" + tags + '}';
54 | }
55 |
56 | @Override
57 | public boolean equals(Object o) {
58 | if (this == o) return true;
59 | if (o == null || getClass() != o.getClass()) return false;
60 |
61 | Event event = (Event) o;
62 |
63 | if (!bucket.equals(event.bucket)) return false;
64 | if (!id.equals(event.id)) return false;
65 | if (!tags.equals(event.tags)) return false;
66 | if (!type.equals(event.type)) return false;
67 |
68 | return true;
69 | }
70 |
71 | @Override
72 | public int hashCode() {
73 | int result = id.hashCode();
74 | result = 31 * result + type.hashCode();
75 | result = 31 * result + bucket.hashCode();
76 | result = 31 * result + tags.hashCode();
77 | return result;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/example/domain/EventRepository.java:
--------------------------------------------------------------------------------
1 | package example.domain;
2 |
3 | import org.springframework.data.cassandra.repository.CassandraRepository;
4 | import org.springframework.data.cassandra.repository.Query;
5 |
6 | public interface EventRepository extends CassandraRepository {
7 |
8 | @Query("select * from event where type = ?0 and bucket=?1")
9 | Iterable findByTypeAndBucket(String type, String bucket);
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/resources/cassandra.properties:
--------------------------------------------------------------------------------
1 | cassandra.contactpoints=127.0.0.1
2 | cassandra.port=9042
3 | cassandra.keyspace=events
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | %d{HH:mm:ss.SSS} [%thread] %-5level %-50logger{50} - %msg%n
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/test/java/example/BaseIntegrationTest.java:
--------------------------------------------------------------------------------
1 | package example;
2 |
3 | import example.domain.Event;
4 | import org.junit.Before;
5 | import org.junit.runner.RunWith;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.cassandra.core.cql.CqlIdentifier;
8 | import org.springframework.data.cassandra.core.CassandraAdminOperations;
9 | import org.springframework.test.context.ContextConfiguration;
10 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11 |
12 | import java.util.HashMap;
13 |
14 | @RunWith(SpringJUnit4ClassRunner.class)
15 | @ContextConfiguration(classes = CassandraConfiguration.class)
16 | public abstract class BaseIntegrationTest {
17 |
18 | @Autowired
19 | private CassandraAdminOperations adminTemplate;
20 |
21 | @Before
22 | public void resetKeySpace() {
23 | adminTemplate.dropTable(CqlIdentifier.cqlId("event"));
24 | adminTemplate.createTable(true, CqlIdentifier.cqlId("event"), Event.class, new HashMap());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/example/CassandraTemplateIntegrationTest.java:
--------------------------------------------------------------------------------
1 | package example;
2 |
3 | import com.datastax.driver.core.querybuilder.QueryBuilder;
4 | import com.datastax.driver.core.querybuilder.Select;
5 | import com.datastax.driver.core.utils.UUIDs;
6 | import com.google.common.collect.ImmutableSet;
7 | import example.domain.Event;
8 | import org.hamcrest.core.IsEqual;
9 | import org.junit.Test;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.data.cassandra.core.CassandraOperations;
12 |
13 | import java.util.List;
14 |
15 | import static org.hamcrest.CoreMatchers.hasItem;
16 | import static org.hamcrest.CoreMatchers.is;
17 | import static org.junit.Assert.assertThat;
18 |
19 | public class CassandraTemplateIntegrationTest extends BaseIntegrationTest {
20 |
21 | public static final String TIME_BUCKET = "2014-01-01";
22 |
23 | @Autowired
24 | private CassandraOperations cassandraTemplate;
25 |
26 | @Test
27 | public void supportsPojoToCqlMappings() {
28 | Event event = new Event(UUIDs.timeBased(), "type1", TIME_BUCKET, ImmutableSet.of("tag1", "tag3"));
29 | cassandraTemplate.insert(event);
30 |
31 | Select select = QueryBuilder.select().from("event").where(QueryBuilder.eq("type", "type1")).and(QueryBuilder.eq("bucket", TIME_BUCKET)).limit(10);
32 |
33 | Event retrievedEvent = cassandraTemplate.selectOne(select, Event.class);
34 |
35 | assertThat(retrievedEvent, IsEqual.equalTo(event));
36 |
37 | List retrievedEvents = cassandraTemplate.select(select, Event.class);
38 |
39 | assertThat(retrievedEvents.size(), is(1));
40 | assertThat(retrievedEvents, hasItem(event));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/test/java/example/CqlTemplateIntegrationTest.java:
--------------------------------------------------------------------------------
1 | package example;
2 |
3 | import com.datastax.driver.core.PreparedStatement;
4 | import com.datastax.driver.core.ResultSet;
5 | import com.datastax.driver.core.Statement;
6 | import com.datastax.driver.core.querybuilder.Insert;
7 | import com.datastax.driver.core.querybuilder.QueryBuilder;
8 | import com.datastax.driver.core.querybuilder.Select;
9 | import com.datastax.driver.core.utils.UUIDs;
10 | import com.google.common.collect.ImmutableSet;
11 | import org.hamcrest.core.Is;
12 | import org.junit.Test;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.cassandra.core.CqlOperations;
15 |
16 | import static org.junit.Assert.assertThat;
17 |
18 | public class CqlTemplateIntegrationTest extends BaseIntegrationTest {
19 |
20 | public static final String TIME_BUCKET = "2014-01-01";
21 |
22 | @Autowired
23 | private CqlOperations cqlTemplate;
24 |
25 | @Test
26 | public void allowsExecutingCqlStatements() {
27 | insertEventUsingCqlString();
28 | insertEventUsingStatementBuildWithQueryBuilder();
29 | insertEventUsingPreparedStatement();
30 |
31 | ResultSet resultSet1 = cqlTemplate.query("select * from event where type='type2' and bucket='" + TIME_BUCKET + "'");
32 |
33 | assertThat(resultSet1.all().size(), Is.is(2));
34 |
35 | Select select = QueryBuilder.select().from("event").where(QueryBuilder.eq("type", "type1")).and(QueryBuilder.eq("bucket", TIME_BUCKET)).limit(10);
36 | ResultSet resultSet2 = cqlTemplate.query(select);
37 |
38 | assertThat(resultSet2.all().size(), Is.is(1));
39 | }
40 |
41 | private void insertEventUsingCqlString() {
42 | cqlTemplate.execute("insert into event (id, type, bucket, tags) values (" + UUIDs.timeBased() + ", 'type1', '" + TIME_BUCKET + "', {'tag2', 'tag3'})");
43 | }
44 |
45 | private void insertEventUsingStatementBuildWithQueryBuilder() {
46 | Insert insertStatement = QueryBuilder.insertInto("event").value("id", UUIDs.timeBased()).value("type", "type2")
47 | .value("bucket", TIME_BUCKET).value("tags", ImmutableSet.of("tag1"));
48 | cqlTemplate.execute(insertStatement);
49 | }
50 |
51 | private void insertEventUsingPreparedStatement() {
52 | PreparedStatement preparedStatement = cqlTemplate.getSession().prepare("insert into event (id, type, bucket, tags) values (?, ?, ?, ?)");
53 | Statement insertStatement = preparedStatement.bind(UUIDs.timeBased(), "type2", TIME_BUCKET, ImmutableSet.of("tag1", "tag2"));
54 | cqlTemplate.execute(insertStatement);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/java/example/EventRepositoryIntegrationTest.java:
--------------------------------------------------------------------------------
1 | package example;
2 |
3 | import com.datastax.driver.core.utils.UUIDs;
4 | import com.google.common.collect.ImmutableSet;
5 | import example.domain.Event;
6 | import example.domain.EventRepository;
7 | import org.junit.Test;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 |
10 | import static org.hamcrest.CoreMatchers.hasItem;
11 | import static org.hamcrest.CoreMatchers.not;
12 | import static org.junit.Assert.assertThat;
13 |
14 | public class EventRepositoryIntegrationTest extends BaseIntegrationTest {
15 |
16 | public static final String TIME_BUCKET = "2014-01-01";
17 |
18 | @Autowired
19 | private EventRepository eventRepository;
20 |
21 | @Test
22 | public void repositoryStoresAndRetrievesEvents() {
23 | Event event1 = new Event(UUIDs.timeBased(), "type1", TIME_BUCKET, ImmutableSet.of("tag1", "tag2"));
24 | Event event2 = new Event(UUIDs.timeBased(), "type1", TIME_BUCKET, ImmutableSet.of("tag3"));
25 | eventRepository.save(ImmutableSet.of(event1, event2));
26 |
27 | Iterable events = eventRepository.findByTypeAndBucket("type1", TIME_BUCKET);
28 |
29 | assertThat(events, hasItem(event1));
30 | assertThat(events, hasItem(event2));
31 | }
32 |
33 | @Test
34 | public void repositoryDeletesStoredEvents() {
35 | Event event1 = new Event(UUIDs.timeBased(), "type1", TIME_BUCKET, ImmutableSet.of("tag1", "tag2"));
36 | Event event2 = new Event(UUIDs.timeBased(), "type1", TIME_BUCKET, ImmutableSet.of("tag3"));
37 | eventRepository.save(ImmutableSet.of(event1, event2));
38 |
39 | eventRepository.delete(event1);
40 | eventRepository.delete(event2);
41 |
42 | Iterable events = eventRepository.findByTypeAndBucket("type1", TIME_BUCKET);
43 |
44 | assertThat(events, not(hasItem(event1)));
45 | assertThat(events, not(hasItem(event2)));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------