IN PROGRESS - issue DATACASS-32: Implement the TemplateAPI for CQL

https://jira.springsource.org/browse/DATACASS-32

Completed alter table Implementation in Template
This commit is contained in:
dwebb
2013-11-13 10:48:02 -05:00
parent 7250d0cc78
commit 4c620a8319
8 changed files with 557 additions and 190 deletions

View File

@@ -47,45 +47,43 @@ import com.datastax.driver.core.TableMetadata;
import com.datastax.driver.core.exceptions.NoHostAvailableException;
/**
* Convenient factory for configuring a Cassandra Session.
* Session is a thread safe singleton and created per a keyspace.
* So, it is enough to have one session per application.
* Convenient factory for configuring a Cassandra Session. Session is a thread safe singleton and created per a
* keyspace. So, it is enough to have one session per application.
*
* @author Alex Shvid
*/
public class CassandraKeyspaceFactoryBean implements FactoryBean<Keyspace>,
InitializingBean, DisposableBean, BeanClassLoaderAware, PersistenceExceptionTranslator {
public class CassandraKeyspaceFactoryBean implements FactoryBean<Keyspace>, InitializingBean, DisposableBean,
BeanClassLoaderAware, PersistenceExceptionTranslator {
private static final Logger log = LoggerFactory.getLogger(CassandraKeyspaceFactoryBean.class);
public static final String DEFAULT_REPLICATION_STRATEGY = "SimpleStrategy";
public static final int DEFAULT_REPLICATION_FACTOR = 1;
private ClassLoader beanClassLoader;
private Cluster cluster;
private Session session;
private String keyspace;
private CassandraConverter converter;
private MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext;
private Keyspace keyspaceBean;
private KeyspaceAttributes keyspaceAttributes;
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
public Keyspace getObject() throws Exception {
public Keyspace getObject() {
return keyspaceBean;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
@@ -101,7 +99,7 @@ InitializingBean, DisposableBean, BeanClassLoaderAware, PersistenceExceptionTran
public boolean isSingleton() {
return true;
}
/*
* (non-Javadoc)
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
@@ -109,149 +107,146 @@ InitializingBean, DisposableBean, BeanClassLoaderAware, PersistenceExceptionTran
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
return exceptionTranslator.translateExceptionIfPossible(ex);
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
if (this.converter == null) {
this.converter = getDefaultCassandraConverter();
}
this.mappingContext = this.converter.getMappingContext();
if (cluster == null) {
throw new IllegalArgumentException(
"at least one cluster is required");
throw new IllegalArgumentException("at least one cluster is required");
}
Session session = null;
session = cluster.connect();
if (StringUtils.hasText(keyspace)) {
KeyspaceMetadata keyspaceMetadata = cluster.getMetadata().getKeyspace(keyspace.toLowerCase());
boolean keyspaceExists = keyspaceMetadata != null;
boolean keyspaceCreated = false;
if (keyspaceExists) {
log.info("keyspace exists " + keyspaceMetadata.asCQLQuery());
}
if (keyspaceAttributes == null) {
keyspaceAttributes = new KeyspaceAttributes();
}
// drop the old keyspace if needed
if (keyspaceExists && (keyspaceAttributes.isCreate() || keyspaceAttributes.isCreateDrop())) {
log.info("Drop keyspace " + keyspace + " on afterPropertiesSet");
session.execute("DROP KEYSPACE " + keyspace);
keyspaceExists = false;
}
// create the new keyspace if needed
if (!keyspaceExists && (keyspaceAttributes.isCreate() || keyspaceAttributes.isCreateDrop() || keyspaceAttributes.isUpdate())) {
}
// create the new keyspace if needed
if (!keyspaceExists
&& (keyspaceAttributes.isCreate() || keyspaceAttributes.isCreateDrop() || keyspaceAttributes.isUpdate())) {
String query = String
.format(
"CREATE KEYSPACE %1$s WITH replication = { 'class' : '%2$s', 'replication_factor' : %3$d } AND DURABLE_WRITES = %4$b",
keyspace, keyspaceAttributes.getReplicationStrategy(), keyspaceAttributes.getReplicationFactor(),
keyspaceAttributes.isDurableWrites());
String query = String.format("CREATE KEYSPACE %1$s WITH replication = { 'class' : '%2$s', 'replication_factor' : %3$d } AND DURABLE_WRITES = %4$b",
keyspace,
keyspaceAttributes.getReplicationStrategy(),
keyspaceAttributes.getReplicationFactor(),
keyspaceAttributes.isDurableWrites());
log.info("Create keyspace " + keyspace + " on afterPropertiesSet " + query);
session.execute(query);
keyspaceCreated = true;
}
// update keyspace if needed
if (keyspaceAttributes.isUpdate() && !keyspaceCreated) {
if (compareKeyspaceAttributes(keyspaceAttributes, keyspaceMetadata) != null) {
String query = String.format("ALTER KEYSPACE %1$s WITH replication = { 'class' : '%2$s', 'replication_factor' : %3$d } AND DURABLE_WRITES = %4$b",
keyspace,
keyspaceAttributes.getReplicationStrategy(),
keyspaceAttributes.getReplicationFactor(),
keyspaceAttributes.isDurableWrites());
String query = String
.format(
"ALTER KEYSPACE %1$s WITH replication = { 'class' : '%2$s', 'replication_factor' : %3$d } AND DURABLE_WRITES = %4$b",
keyspace, keyspaceAttributes.getReplicationStrategy(), keyspaceAttributes.getReplicationFactor(),
keyspaceAttributes.isDurableWrites());
log.info("Update keyspace " + keyspace + " on afterPropertiesSet " + query);
session.execute(query);
}
}
// validate keyspace if needed
if (keyspaceAttributes.isValidate()) {
if (!keyspaceExists) {
throw new InvalidDataAccessApiUsageException("keyspace '" + keyspace + "' not found in the Cassandra");
}
String errorField = compareKeyspaceAttributes(keyspaceAttributes, keyspaceMetadata);
if (errorField != null) {
throw new InvalidDataAccessApiUsageException(errorField + " attribute is not much in the keyspace '" + keyspace + "'");
throw new InvalidDataAccessApiUsageException(errorField + " attribute is not much in the keyspace '"
+ keyspace + "'");
}
}
session.execute("USE " + keyspace);
if (!CollectionUtils.isEmpty(keyspaceAttributes.getTables())) {
for (TableAttributes tableAttributes : keyspaceAttributes.getTables()) {
String entityClassName = tableAttributes.getEntity();
Class<?> entityClass = ClassUtils.forName(entityClassName, this.beanClassLoader);
CassandraPersistentEntity<?> entity = determineEntity(entityClass);
String useTableName = tableAttributes.getName() != null ? tableAttributes.getName() : entity.getTable();
if (keyspaceCreated) {
createNewTable(session, useTableName, entity);
}
else if (keyspaceAttributes.isUpdate()) {
} else if (keyspaceAttributes.isUpdate()) {
TableMetadata table = keyspaceMetadata.getTable(useTableName.toLowerCase());
if (table == null) {
createNewTable(session, useTableName, entity);
}
else {
} else {
// alter table columns
for (String cql : CQLUtils.alterTable(useTableName, entity, table)) {
log.info("Execute on keyspace " + keyspace + " CQL " + cql);
session.execute(cql);
}
}
}
else if (keyspaceAttributes.isValidate()) {
} else if (keyspaceAttributes.isValidate()) {
TableMetadata table = keyspaceMetadata.getTable(useTableName.toLowerCase());
if (table == null) {
throw new InvalidDataAccessApiUsageException("not found table " + useTableName + " for entity " + entityClassName);
throw new InvalidDataAccessApiUsageException("not found table " + useTableName + " for entity "
+ entityClassName);
}
// validate columns
List<String> alter = CQLUtils.alterTable(useTableName, entity, table);
if (!alter.isEmpty()) {
throw new InvalidDataAccessApiUsageException("invalid table " + useTableName + " for entity " + entityClassName + ". modify it by " + alter);
throw new InvalidDataAccessApiUsageException("invalid table " + useTableName + " for entity "
+ entityClassName + ". modify it by " + alter);
}
}
//System.out.println("tableAttributes, entityClass=" + entityClass + ", table = " + entity.getTable());
// System.out.println("tableAttributes, entityClass=" + entityClass + ", table = " + entity.getTable());
}
}
}
}
// initialize property
this.session = session;
this.keyspaceBean = new Keyspace(keyspace, session, converter);
}
private void createNewTable(Session session, String useTableName,
CassandraPersistentEntity<?> entity)
private void createNewTable(Session session, String useTableName, CassandraPersistentEntity<?> entity)
throws NoHostAvailableException {
String cql = CQLUtils.createTable(useTableName, entity);
log.info("Execute on keyspace " + keyspace + " CQL " + cql);
@@ -261,13 +256,13 @@ InitializingBean, DisposableBean, BeanClassLoaderAware, PersistenceExceptionTran
session.execute(indexCQL);
}
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.DisposableBean#destroy()
*/
public void destroy() throws Exception {
if (StringUtils.hasText(keyspace) && keyspaceAttributes != null && keyspaceAttributes.isCreateDrop()) {
log.info("Drop keyspace " + keyspace + " on destroy");
session.execute("USE system");
@@ -287,12 +282,13 @@ InitializingBean, DisposableBean, BeanClassLoaderAware, PersistenceExceptionTran
public void setKeyspaceAttributes(KeyspaceAttributes keyspaceAttributes) {
this.keyspaceAttributes = keyspaceAttributes;
}
public void setConverter(CassandraConverter converter) {
this.converter = converter;
}
private static String compareKeyspaceAttributes(KeyspaceAttributes keyspaceAttributes, KeyspaceMetadata keyspaceMetadata) {
private static String compareKeyspaceAttributes(KeyspaceAttributes keyspaceAttributes,
KeyspaceMetadata keyspaceMetadata) {
if (keyspaceAttributes.isDurableWrites() != keyspaceMetadata.isDurableWrites()) {
return "durableWrites";
}
@@ -306,11 +302,10 @@ InitializingBean, DisposableBean, BeanClassLoaderAware, PersistenceExceptionTran
if (keyspaceAttributes.getReplicationFactor() != replicationFactor) {
return "replication_factor";
}
}
catch(NumberFormatException e) {
} catch (NumberFormatException e) {
return "replication_factor";
}
String attributesStrategy = keyspaceAttributes.getReplicationStrategy();
if (attributesStrategy.indexOf('.') == -1) {
attributesStrategy = "org.apache.cassandra.locator." + attributesStrategy;
@@ -321,7 +316,7 @@ InitializingBean, DisposableBean, BeanClassLoaderAware, PersistenceExceptionTran
}
return null;
}
CassandraPersistentEntity<?> determineEntity(Class<?> entityClass) {
if (entityClass == null) {
@@ -336,7 +331,7 @@ InitializingBean, DisposableBean, BeanClassLoaderAware, PersistenceExceptionTran
}
return entity;
}
private static final CassandraConverter getDefaultCassandraConverter() {
MappingCassandraConverter converter = new MappingCassandraConverter(new CassandraMappingContext());
converter.afterPropertiesSet();

View File

@@ -22,6 +22,7 @@ import org.springframework.data.cassandra.dto.RingMember;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.TableMetadata;
/**
* @author Alex Shvid
@@ -43,6 +44,14 @@ public interface CassandraOperations {
*/
String getTableName(Class<?> entityClass);
/**
* Get the metatdata for the given entityClass table mapping
*
* @param entityClass
* @return The table metadata
*/
TableMetadata getTableMetadata(Class<?> entityClass, final String tableName);
/**
* Execute query and return Cassandra ResultSet
*

View File

@@ -47,6 +47,7 @@ import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.TableMetadata;
import com.datastax.driver.core.exceptions.NoHostAvailableException;
/**
@@ -531,8 +532,7 @@ public class CassandraTemplate implements CassandraOperations {
*/
@Override
public void alterTable(Class<?> entityClass) {
// TODO Auto-generated method stub
alterTable(entityClass, getTableName(entityClass));
}
/* (non-Javadoc)
@@ -540,7 +540,40 @@ public class CassandraTemplate implements CassandraOperations {
*/
@Override
public void alterTable(Class<?> entityClass, String tableName) {
// TODO Auto-generated method stub
doAlterTable(entityClass, tableName);
}
/**
* Create a list of query operations to alter the table for the given entity
*
* @param entityClass
* @param tableName
*/
protected void doAlterTable(Class<?> entityClass, String tableName) {
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
Assert.notNull(entity);
final TableMetadata tableMetadata = getTableMetadata(entityClass, tableName);
final List<String> queryList = CQLUtils.alterTable(tableName, entity, tableMetadata);
execute(new SessionCallback<Object>() {
public Object doInSession(Session s) throws DataAccessException {
for (String q : queryList) {
log.info(q);
s.execute(q);
}
return null;
}
});
}
@@ -562,4 +595,34 @@ public class CassandraTemplate implements CassandraOperations {
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraOperations#getTableMetadata(java.lang.Class)
*/
@Override
public TableMetadata getTableMetadata(Class<?> entityClass, String tableName) {
/*
* Determine the table name if not provided
*/
if (tableName == null) {
tableName = getTableName(entityClass);
}
Assert.notNull(tableName);
final String metadataTableName = tableName;
return execute(new SessionCallback<TableMetadata>() {
public TableMetadata doInSession(Session s) throws DataAccessException {
log.info("Keyspace => " + keyspace.getKeyspace());
return s.getCluster().getMetadata().getKeyspace(keyspace.getKeyspace()).getTable(metadataTableName);
}
});
}
}

View File

@@ -2,6 +2,8 @@ package org.springframework.data.cassandra.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.core.CassandraKeyspaceFactoryBean;
import org.springframework.data.cassandra.core.CassandraTemplate;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Cluster.Builder;
@@ -10,17 +12,17 @@ import com.datastax.driver.core.Cluster.Builder;
* Setup any spring configuration for unit tests
*
* @author David Webb
*
*
*/
@Configuration
public class TestConfig extends AbstractCassandraConfiguration {
/* (non-Javadoc)
* @see org.springframework.data.cassandra.config.AbstractCassandraConfiguration#getKeyspaceName()
*/
@Override
protected String getKeyspaceName() {
return null;
return "test";
}
/* (non-Javadoc)
@@ -28,13 +30,33 @@ public class TestConfig extends AbstractCassandraConfiguration {
*/
@Override
@Bean
public Cluster cluster() throws Exception {
public Cluster cluster() {
Builder builder = Cluster.builder();
builder.addContactPoint("127.0.0.1");
return builder.build();
}
@Bean
public CassandraKeyspaceFactoryBean keyspaceFactoryBean() {
CassandraKeyspaceFactoryBean bean = new CassandraKeyspaceFactoryBean();
bean.setCluster(cluster());
bean.setKeyspace("test");
return bean;
}
@Bean
public CassandraTemplate cassandraTemplate() {
CassandraTemplate template = new CassandraTemplate(keyspaceFactoryBean().getObject());
return template;
}
}

View File

@@ -0,0 +1,92 @@
/**
* All BrightMove Code is Copyright 2004-2013 BrightMove Inc.
* Modification of code without the express written consent of
* BrightMove, Inc. is strictly forbidden.
*
* Author: David Webb (dwebb@brightmove.com)
* Created On: Nov 11, 2013
*/
package org.springframework.data.cassandra.template;
import java.io.IOException;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.DataLoader;
import org.cassandraunit.dataset.yaml.ClassPathYamlDataSet;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.cassandra.config.TestConfig;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.test.User;
import org.springframework.data.cassandra.test.UserAlter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
/**
* @author David Webb (dwebb@brightmove.com)
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class)
public class CassandraOperationsAlterTableTest {
@Autowired
private CassandraTemplate cassandraTemplate;
@Mock
ApplicationContext context;
private static Logger log = LoggerFactory.getLogger(CassandraOperationsAlterTableTest.class);
@BeforeClass
public static void startCassandra() throws IOException, TTransportException, ConfigurationException,
InterruptedException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra("cassandra.yaml");
/*
* Load data file to creat the test keyspace before we init the template
*/
DataLoader dataLoader = new DataLoader("Test Cluster", "localhost:9160");
dataLoader.load(new ClassPathYamlDataSet("cassandra-data.yaml"));
}
@Before
public void setupKeyspace() {
cassandraTemplate.executeQuery("use test;");
log.info("Creating Table...");
cassandraTemplate.createTable(User.class);
}
@Test
public void alterTableTest() {
cassandraTemplate.alterTable(UserAlter.class);
}
@After
public void clearCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
@AfterClass
public static void stopCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
}

View File

@@ -11,12 +11,15 @@ package org.springframework.data.cassandra.template;
import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import junit.framework.Assert;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.DataLoader;
import org.cassandraunit.dataset.yaml.ClassPathYamlDataSet;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.After;
import org.junit.AfterClass;
@@ -29,8 +32,9 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.cassandra.config.TestConfig;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.dto.RingMember;
import org.springframework.data.cassandra.test.LogEntry;
import org.springframework.data.cassandra.test.User;
import org.springframework.data.cassandra.vo.RingMember;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
@@ -39,111 +43,129 @@ import com.datastax.driver.core.Session;
/**
* @author David Webb (dwebb@brightmove.com)
*
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration (classes = {TestConfig.class}, loader = AnnotationConfigContextLoader.class)
@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class)
public class CassandraOperationsTest {
@Autowired
private CassandraTemplate cassandraTemplate;
private static Logger log = LoggerFactory.getLogger(CassandraOperationsTest.class);
protected Session session;
@BeforeClass
public static void startCassandra()
throws IOException, TTransportException, ConfigurationException, InterruptedException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra("cassandra.yaml");
}
@Before
public void setupKeyspace() {
log.info("Creating Keyspace...");
cassandraTemplate.executeQuery("CREATE KEYSPACE test WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };");
log.info("Using Keyspace...");
protected Session session;
cassandraTemplate.executeQuery("use test;");
@BeforeClass
public static void startCassandra() throws IOException, TTransportException, ConfigurationException,
InterruptedException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra("cassandra.yaml");
log.info("Creating Table...");
cassandraTemplate.createTable(User.class);
}
@Test
public void ringTest() {
List<RingMember> ring = cassandraTemplate.describeRing();
/*
* There must be 1 node in the cluster if the embedded server is running.
* Load data file to creat the test keyspace before we init the template
*/
DataLoader dataLoader = new DataLoader("Test Cluster", "localhost:9160");
dataLoader.load(new ClassPathYamlDataSet("cassandra-data.yaml"));
}
@Before
public void setupKeyspace() {
/*
* Load data file to creat the test keyspace before we init the template
*/
DataLoader dataLoader = new DataLoader("Test Cluster", "localhost:9160");
dataLoader.load(new ClassPathYamlDataSet("cassandra-data.yaml"));
log.info("Creating Table...");
cassandraTemplate.createTable(User.class);
cassandraTemplate.createTable(LogEntry.class);
}
@Test
public void ringTest() {
List<RingMember> ring = cassandraTemplate.describeRing();
/*
* There must be 1 node in the cluster if the embedded server is
* running.
*/
assertNotNull(ring);
for (RingMember h: ring) {
for (RingMember h : ring) {
log.info(h.address);
}
}
/**
* This test inserts and selects users from the test.users table
* This is testing the CassandraTemplate:
* <ul>
* <li>insert()</li>
* <li>selectOne()</li>
* <li>select()</li>
* <li>remove()</li>
* </ul>
*/
@Test
public void UsersTest() {
User u = new User();
u.setUsername("cassandra");
u.setFirstName("Apache");
u.setLastName("Cassnadra");
u.setAge(40);
cassandraTemplate.insert(u, "users");
User us = cassandraTemplate.selectOne("select * from test.users where username='cassandra';" , User.class);
log.debug("Output from select One");
log.debug(us.getFirstName());
log.debug(us.getLastName());
List<User> users = cassandraTemplate.select("Select * from test.users", User.class);
}
log.debug("Output from select All");
for (User x: users) {
log.debug(x.getFirstName());
log.debug(x.getLastName());
}
cassandraTemplate.remove(u);
User delUser = cassandraTemplate.selectOne("select * from test.users where username='cassandra';" , User.class);
log.info("delUser => " + delUser);
Assert.assertNull(delUser);
}
@After
public void clearCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
/**
* This test inserts and selects users from the test.users table This is testing the CassandraTemplate:
* <ul>
* <li>insert()</li>
* <li>selectOne()</li>
* <li>select()</li>
* <li>remove()</li>
* </ul>
*/
@Test
public void UsersTest() {
@AfterClass
public static void stopCassandra() {
EmbeddedCassandraServerHelper.stopEmbeddedCassandra();
}
User u = new User();
u.setUsername("cassandra");
u.setFirstName("Apache");
u.setLastName("Cassnadra");
u.setAge(40);
cassandraTemplate.insert(u, "users");
User us = cassandraTemplate.selectOne("select * from test.users where username='cassandra';", User.class);
log.debug("Output from select One");
log.debug(us.getFirstName());
log.debug(us.getLastName());
List<User> users = cassandraTemplate.select("Select * from test.users", User.class);
log.debug("Output from select All");
for (User x : users) {
log.debug(x.getFirstName());
log.debug(x.getLastName());
}
cassandraTemplate.remove(u);
User delUser = cassandraTemplate.selectOne("select * from test.users where username='cassandra';", User.class);
log.info("delUser => " + delUser);
Assert.assertNull(delUser);
}
// @Test
public void multiplePKTest() {
LogEntry l = new LogEntry();
l.setLogDate(new Date());
l.setHostname("localhost");
l.setLogData("Host is Up");
cassandraTemplate.insert(l);
}
@After
public void clearCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
@AfterClass
public static void stopCassandra() {
EmbeddedCassandraServerHelper.stopEmbeddedCassandra();
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test;
import java.util.Set;
import org.springframework.data.annotation.Id;
import org.springframework.data.cassandra.mapping.Index;
import org.springframework.data.cassandra.mapping.Table;
/**
* This is an example of the Users statis table, where all fields are columns in Cassandra row. Some fields can be
* Set,List,Map like emails.
*
* User contains base information related for separate user, like names, additional information, emails, following
* users, friends.
*
* @author Alex Shvid
*/
@Table(name = "users")
public class UserAlter {
/*
* Primary Row ID
*/
@Id
private String username;
/*
* Public information
*/
private String firstName;
private String lastName;
/*
* Secondary index, used only on fields with common information,
* not effective on email, username
*/
@Index
private String place;
private String nickName;
/*
* Password
*/
private String password;
/*
* Age
*/
private int age;
/*
* Following other users in userline
*/
private Set<String> following;
/*
* Friends of the user
*/
private Set<String> friends;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<String> getFollowing() {
return following;
}
public void setFollowing(Set<String> following) {
this.following = following;
}
public Set<String> getFriends() {
return friends;
}
public void setFriends(Set<String> friends) {
this.friends = friends;
}
/**
* @return Returns the age.
*/
public int getAge() {
return age;
}
/**
* @param age The age to set.
*/
public void setAge(int age) {
this.age = age;
}
/**
* @return Returns the nickName.
*/
public String getNickName() {
return nickName;
}
/**
* @param nickName The nickName to set.
*/
public void setNickName(String nickName) {
this.nickName = nickName;
}
}

View File

@@ -0,0 +1,3 @@
name: test
replicationFactor: 1
strategy: org.apache.cassandra.locator.SimpleStrategy