#553 - Adapt Spring Data Cassandra.

This commit is contained in:
Mark Paluch
2020-02-10 15:28:29 +01:00
parent c88ad331c0
commit 523d2c8a56
18 changed files with 72 additions and 97 deletions

View File

@@ -28,7 +28,7 @@ import org.springframework.core.convert.converter.Converter;
import org.springframework.data.cassandra.core.convert.CassandraCustomConversions;
import org.springframework.util.StringUtils;
import com.datastax.driver.core.Row;
import com.datastax.oss.driver.api.core.cql.Row;
import com.fasterxml.jackson.databind.ObjectMapper;
/**

View File

@@ -23,8 +23,7 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.cassandra.core.mapping.CassandraType;
import org.springframework.data.cassandra.core.mapping.Table;
import com.datastax.driver.core.DataType.Name;
import com.datastax.driver.core.UDTValue;
import com.datastax.oss.driver.api.core.data.UdtValue;
/**
* @author Mark Paluch
@@ -39,6 +38,5 @@ public class Person {
Address current;
List<Address> previous;
@CassandraType(type = Name.UDT, userTypeName = "address")
UDTValue alternative;
@CassandraType(type = CassandraType.Name.UDT, userTypeName = "address") UdtValue alternative;
}

View File

@@ -1,2 +1,3 @@
spring.data.cassandra.keyspace-name=example
spring.data.cassandra.schema-action=recreate
spring.data.cassandra.local-datacenter=datacenter1

View File

@@ -25,12 +25,13 @@ import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.util.Version;
import org.springframework.test.context.junit4.SpringRunner;
import com.datastax.driver.core.Session;
import com.datastax.oss.driver.api.core.CqlSession;
/**
* Integration test showing the basic usage of {@link BasicUserRepository}.
@@ -49,7 +50,7 @@ public class BasicUserRepositoryTests {
@ClassRule public final static CassandraKeyspace CASSANDRA_KEYSPACE = CassandraKeyspace.onLocalhost();
@Autowired BasicUserRepository repository;
@Autowired Session session;
@Autowired CqlSession session;
User user;
@Before

View File

@@ -28,6 +28,7 @@ import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.cassandra.core.AsyncCassandraTemplate;
@@ -36,10 +37,10 @@ import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.concurrent.ListenableFuture;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.cql.Row;
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
/**
* Integration test showing the basic usage of {@link CassandraTemplate}.
@@ -52,7 +53,7 @@ public class CassandraOperationsIntegrationTests {
@ClassRule public final static CassandraKeyspace CASSANDRA_KEYSPACE = CassandraKeyspace.onLocalhost();
@Autowired Session session;
@Autowired CqlSession session;
@Autowired CassandraOperations template;
@Before
@@ -67,18 +68,18 @@ public class CassandraOperationsIntegrationTests {
@Test
public void insertAndSelect() {
Insert insert = QueryBuilder.insertInto("users").value("user_id", 42L) //
.value("uname", "heisenberg") //
.value("fname", "Walter") //
.value("lname", "White") //
Insert insert = QueryBuilder.insertInto("users").value("user_id", QueryBuilder.literal(42L)) //
.value("uname", QueryBuilder.literal("heisenberg")) //
.value("fname", QueryBuilder.literal("Walter")) //
.value("lname", QueryBuilder.literal("White")) //
.ifNotExists(); //
template.getCqlOperations().execute(insert);
template.getCqlOperations().execute(insert.asCql());
User user = template.selectOneById(42L, User.class);
assertThat(user.getUsername()).isEqualTo("heisenberg");
List<User> users = template.select(QueryBuilder.select().from("users"), User.class);
List<User> users = template.select(QueryBuilder.selectFrom("users").all().asCql(), User.class);
assertThat(users).hasSize(1);
assertThat(users.get(0)).isEqualTo(user);
}
@@ -148,13 +149,13 @@ public class CassandraOperationsIntegrationTests {
template.insert(user);
Long id = template.selectOne(QueryBuilder.select("user_id").from("users"), Long.class);
Long id = template.selectOne(QueryBuilder.selectFrom("users").column("user_id").asCql(), Long.class);
assertThat(id).isEqualTo(user.getId());
Row row = template.selectOne(QueryBuilder.select("user_id").from("users"), Row.class);
Row row = template.selectOne(QueryBuilder.selectFrom("users").column("user_id").asCql(), Row.class);
assertThat(row.getLong(0)).isEqualTo(user.getId());
Map<String, Object> map = template.selectOne(QueryBuilder.select().from("users"), Map.class);
Map<String, Object> map = template.selectOne(QueryBuilder.selectFrom("users").all().asCql(), Map.class);
assertThat(map).containsEntry("user_id", user.getId());
assertThat(map).containsEntry("fname", "Walter");
}

View File

@@ -17,6 +17,9 @@ package example.springdata.cassandra.convert;
import static org.assertj.core.api.Assertions.*;
import com.datastax.oss.driver.api.core.cql.Row;
import com.datastax.oss.driver.api.core.data.TupleValue;
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
import example.springdata.cassandra.util.CassandraKeyspace;
import java.util.Arrays;
@@ -33,9 +36,6 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.test.context.junit4.SpringRunner;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.TupleValue;
import com.datastax.driver.core.querybuilder.QueryBuilder;
/**
* @author Mark Paluch
@@ -68,7 +68,7 @@ public class ConversionIntegrationTests {
operations.insert(addressbook);
Row row = operations.selectOne(QueryBuilder.select().from("addressbook"), Row.class);
Row row = operations.selectOne(QueryBuilder.selectFrom("addressbook").all().asCql(), Row.class);
assertThat(row).isNotNull();
@@ -92,7 +92,7 @@ public class ConversionIntegrationTests {
operations.insert(addressbook);
Addressbook loaded = operations.selectOne(QueryBuilder.select().from("addressbook"), Addressbook.class);
Addressbook loaded = operations.selectOne(QueryBuilder.selectFrom("addressbook").all().asCql(), Addressbook.class);
assertThat(loaded.getMe()).isEqualTo(addressbook.getMe());
assertThat(loaded.getFriends()).isEqualTo(addressbook.getFriends());
@@ -113,7 +113,8 @@ public class ConversionIntegrationTests {
operations.insert(addressbook);
CustomAddressbook loaded = operations.selectOne(QueryBuilder.select().from("addressbook"), CustomAddressbook.class);
CustomAddressbook loaded = operations.selectOne(QueryBuilder.selectFrom("addressbook").all().asCql(),
CustomAddressbook.class);
assertThat(loaded.getTheId()).isEqualTo(addressbook.getId());
assertThat(loaded.getMyDetailsAsJson()).contains("\"firstname\":\"Walter\"");
@@ -142,7 +143,7 @@ public class ConversionIntegrationTests {
operations.insert(addressbook);
Row row = operations.selectOne(QueryBuilder.select().from("addressbook"), Row.class);
Row row = operations.selectOne(QueryBuilder.selectFrom("addressbook").all().asCql(), Row.class);
assertThat(row).isNotNull();

View File

@@ -25,6 +25,7 @@ import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Configuration;
@@ -34,9 +35,9 @@ import org.springframework.data.cassandra.core.CassandraAdminOperations;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.test.context.junit4.SpringRunner;
import com.datastax.driver.core.KeyspaceMetadata;
import com.datastax.driver.core.UDTValue;
import com.datastax.driver.core.UserType;
import com.datastax.oss.driver.api.core.data.UdtValue;
import com.datastax.oss.driver.api.core.metadata.schema.KeyspaceMetadata;
import com.datastax.oss.driver.api.core.type.UserDefinedType;
/**
* Integration test to show User-Defined type support.
@@ -58,6 +59,11 @@ public class UserDefinedTypeIntegrationTest {
return "example";
}
@Override
protected String getLocalDataCenter() {
return "datacenter1";
}
@Override
public String[] getEntityBasePackages() {
return new String[] { Person.class.getPackage().getName() };
@@ -106,9 +112,9 @@ public class UserDefinedTypeIntegrationTest {
public void insertRawUdt() {
KeyspaceMetadata keyspaceMetadata = adminOperations.getKeyspaceMetadata();
UserType address = keyspaceMetadata.getUserType("address");
UserDefinedType address = keyspaceMetadata.getUserDefinedType("address").get();
UDTValue udtValue = address.newValue();
UdtValue udtValue = address.newValue();
udtValue.setString("street", "308 Negra Arroyo Lane");
udtValue.setString("zip", "87104");
udtValue.setString("city", "Albuquerque");

View File

@@ -35,12 +35,6 @@ public interface OrderRepository extends Repository<Order, String> {
@Query("SELECT * from pizza_orders WHERE orderdate = ?0 and zoneid = ?1 ALLOW FILTERING")
Order findOrderByOrderDateAndZoneId(LocalDate orderDate, ZoneId zoneId);
/**
* Parameter conversion can be overridden by using the {@link CassandraType} annotation.
*/
@Query("SELECT * from pizza_orders WHERE orderdate = ?0 and zoneid = ?1 ALLOW FILTERING")
Order findOrderByDate(com.datastax.driver.core.LocalDate orderDate, String zoneId);
void deleteAll();
Order save(Order order);

View File

@@ -1,2 +1,3 @@
spring.data.cassandra.keyspace-name=example
spring.data.cassandra.schema-action=recreate
spring.data.cassandra.local-datacenter=datacenter1

View File

@@ -59,17 +59,4 @@ public class Jsr310IntegrationTests {
assertThat(repository.findOrderByOrderDateAndZoneId(order.getOrderDate(), order.getZoneId())).isEqualTo(order);
}
@Test
public void findOneByConvertedTypes() {
Order order = new Order("42", LocalDate.of(2010, 1, 2), ZoneId.systemDefault());
repository.save(order);
com.datastax.driver.core.LocalDate date = com.datastax.driver.core.LocalDate.fromYearMonthDay(2010, 1, 2);
String zoneId = order.getZoneId().getId();
assertThat(repository.findOrderByDate(date, zoneId)).isEqualTo(order);
}
}

View File

@@ -1,2 +1,3 @@
spring.data.cassandra.keyspace-name=example
spring.data.cassandra.schema-action=recreate
spring.data.cassandra.local-datacenter=datacenter1

View File

@@ -15,8 +15,8 @@
*/
package example.springdata.cassandra.kotlin
import com.datastax.driver.core.Row
import com.datastax.driver.core.querybuilder.QueryBuilder
import com.datastax.oss.driver.api.core.CqlIdentifier
import com.datastax.oss.driver.api.querybuilder.QueryBuilder
import example.springdata.cassandra.util.CassandraKeyspace
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
@@ -26,7 +26,6 @@ import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.cassandra.core.*
import org.springframework.data.cassandra.core.cql.CqlIdentifier
import org.springframework.data.cassandra.core.query.Query.query
import org.springframework.data.cassandra.core.query.isEqualTo
import org.springframework.data.cassandra.core.query.where
@@ -60,7 +59,7 @@ class TemplateTests {
@Test
fun `should create collection leveraging reified type parameters`() {
assertThat(operations.getTableName<Person>()).isEqualTo(CqlIdentifier.of("person"))
assertThat(operations.getTableName<Person>()).isEqualTo(CqlIdentifier.fromCql("person"))
}
@Test
@@ -115,7 +114,7 @@ class TemplateTests {
@Test
fun `should apply defaulting for absent properties`() {
operations.cqlOperations.execute(QueryBuilder.insertInto("person").value("firstname", "Walter"))
operations.cqlOperations.execute(QueryBuilder.insertInto("person").value("firstname", QueryBuilder.literal("Walter")).asCql())
val person = operations.query<Person>()
.matching(query(where("firstname").isEqualTo("Walter")))

View File

@@ -36,11 +36,6 @@
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
</dependency>
<!-- Required for Embedded Cassandra -->
<dependency>
<groupId>com.codahale.metrics</groupId>

View File

@@ -15,7 +15,6 @@
*/
package example.springdata.cassandra.people;
import static com.datastax.driver.core.querybuilder.QueryBuilder.*;
import static org.assertj.core.api.Assertions.*;
import example.springdata.cassandra.util.CassandraKeyspace;
@@ -87,7 +86,7 @@ public class ReactiveCassandraTemplateIntegrationTest {
@Test
public void convertReactorTypesToRxJava1() throws Exception {
Flux<Person> flux = template.select(select().from("person").where(eq("lastname", "White")), Person.class);
Flux<Person> flux = template.select("SELECT * FROM person WHERE lastname = 'White'", Person.class);
long count = RxReactiveStreams.toObservable(flux) //
.count() //

View File

@@ -1,4 +1,5 @@
spring.data.cassandra.keyspace-name=example
spring.data.cassandra.schema-action=recreate
spring.data.cassandra.local-datacenter=datacenter1
logging.level.org.springframework.data.cassandra=INFO

View File

@@ -1,5 +1,6 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@@ -22,7 +23,7 @@
<dependency>
<groupId>org.apache.cassandra</groupId>
<artifactId>cassandra-all</artifactId>
<version>3.9</version>
<version>3.11.5</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
@@ -39,10 +40,15 @@
</exclusions>
</dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-core</artifactId>
</dependency>
<dependency>
<groupId>org.cassandraunit</groupId>
<artifactId>cassandra-unit</artifactId>
<version>3.1.1.0</version>
<version>4.3.1.0</version>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>

View File

@@ -15,18 +15,14 @@
*/
package example.springdata.cassandra.util;
import io.netty.channel.EventLoopGroup;
import java.util.concurrent.TimeUnit;
import java.net.InetSocketAddress;
import org.junit.AssumptionViolatedException;
import org.springframework.data.util.Version;
import org.springframework.util.Assert;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.NettyOptions;
import com.datastax.driver.core.ProtocolOptions;
import com.datastax.driver.core.Session;
import com.datastax.oss.driver.api.core.CqlSession;
/**
* {@link CassandraResource} to require (create or reuse) an Apache Cassandra keyspace and optionally require a specific
@@ -58,8 +54,8 @@ public class CassandraKeyspace extends CassandraResource {
* @return the {@link CassandraKeyspace} rule.
*/
public static CassandraKeyspace onLocalhost() {
return new CassandraKeyspace("localhost", ProtocolOptions.DEFAULT_PORT, "example",
Cassandra.embeddedIfNotRunning("localhost", ProtocolOptions.DEFAULT_PORT), new Version(0, 0, 0));
return new CassandraKeyspace("localhost", 9042, "example", Cassandra.embeddedIfNotRunning("localhost", 9042),
new Version(0, 0, 0));
}
/**
@@ -97,17 +93,8 @@ public class CassandraKeyspace extends CassandraResource {
dependency.before();
Cluster cluster = Cluster.builder().addContactPoint(getHost()).withPort(getPort())
.withNettyOptions(new NettyOptions() {
@Override
public void onClusterClose(EventLoopGroup eventLoopGroup) {
eventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS).syncUninterruptibly();
}
}).build();
Session session = cluster.newSession();
try {
try (CqlSession session = CqlSession.builder().addContactPoint(new InetSocketAddress(getHost(), getPort()))
.withLocalDatacenter("datacenter1").build()) {
if (requiredVersion != null) {
@@ -122,9 +109,6 @@ public class CassandraKeyspace extends CassandraResource {
session.execute(String.format("CREATE KEYSPACE IF NOT EXISTS %s \n"
+ "WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };", keyspaceName));
} finally {
session.close();
cluster.close();
}
}

View File

@@ -15,14 +15,14 @@
*/
package example.springdata.cassandra.util;
import lombok.experimental.UtilityClass;
import org.springframework.data.util.Version;
import org.springframework.util.Assert;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import lombok.experimental.UtilityClass;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.cql.ResultSet;
import com.datastax.oss.driver.api.core.cql.Row;
/**
* Utility to retrieve the Cassandra release version.
@@ -38,7 +38,7 @@ public class CassandraVersion {
* @param session must not be {@literal null}.
* @return the release {@link Version}.
*/
public static Version getReleaseVersion(Session session) {
public static Version getReleaseVersion(CqlSession session) {
Assert.notNull(session, "Session must not be null");