diff --git a/src/main/java/org/springframework/data/cassandra/convert/CassandraPropertyValueProvider.java b/src/main/java/org/springframework/data/cassandra/convert/CassandraPropertyValueProvider.java index 7801ed96a..229132890 100644 --- a/src/main/java/org/springframework/data/cassandra/convert/CassandraPropertyValueProvider.java +++ b/src/main/java/org/springframework/data/cassandra/convert/CassandraPropertyValueProvider.java @@ -67,6 +67,16 @@ public class CassandraPropertyValueProvider implements PropertyValueProvider getEntity(Object o) { + + CassandraPersistentEntity entity = null; + + try { + String entityClassName = o.getClass().getName(); + Class entityClass = ClassUtils.forName(entityClassName, this.beanClassLoader); + entity = mappingContext.getPersistentEntity(entityClass); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (LinkageError e) { + e.printStackTrace(); + } finally {} + + return entity; + + } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.CassandraOperations#getTableName(java.lang.Class) + */ public String getTableName(Class entityClass) { return determineTableName(entityClass); } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.CassandraOperations#executeQuery(java.lang.String) + */ public ResultSet executeQuery(String query) { try { return session.execute(query); @@ -157,31 +186,27 @@ public class CassandraTemplate implements CassandraOperations { } } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.CassandraOperations#select(java.lang.String, java.lang.Class) + */ public List select(String query, Class selectClass) { return selectInternal(query, new ReadRowCallback(cassandraConverter, selectClass)); } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.CassandraOperations#selectOne(java.lang.String, java.lang.Class) + */ public T selectOne(String query, Class selectClass) { return selectOneInternal(query, new ReadRowCallback(cassandraConverter, selectClass)); } - - + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.CassandraOperations#getConverter() + */ public CassandraConverter getConverter() { return cassandraConverter; } - /** - * Simple internal callback to allow operations on a {@link Row}. - * - * @author Alex Shvid - */ - - private interface RowCallback { - - T doWith(Row object); - } - /** * Simple {@link RowCallback} that will transform {@link Row} into the given target type using the given * {@link EntityReader}. @@ -206,6 +231,11 @@ public class CassandraTemplate implements CassandraOperations { } } + /** + * @param query + * @param readRowCallback + * @return + */ List selectInternal(String query, ReadRowCallback readRowCallback) { try { ResultSet resultSet = session.execute(query); @@ -281,43 +311,37 @@ public class CassandraTemplate implements CassandraOperations { } /** - * Insert a row into a Cassandra ColumnFamily + * Insert a row into a Cassandra CQL Table * * @param tableName * @param objectToSave - * @throws LinkageError - * @throws ClassNotFoundException */ protected T doInsert(final String tableName, final T objectToSave) { + CassandraPersistentEntity entity = getEntity(objectToSave); + + Assert.notNull(entity); + try { - final String entityClassName = objectToSave.getClass().getName(); - final Class entityClass = ClassUtils.forName(entityClassName, this.beanClassLoader); - final CassandraPersistentEntity entity = mappingContext.getPersistentEntity(entityClass); - final String useTableName = tableName != null ? tableName : entity.getTable(); + final Query q = CQLUtils.toInsertQuery(keyspace.getKeyspace(), tableName, objectToSave, entity); + log.info(q.toString()); return execute(new SessionCallback() { public T doInSession(Session s) throws DataAccessException { + + s.execute(q); - Query q = CQLUtils.toInsertQuery(keyspace.getKeyspace(), useTableName, entity, objectToSave); - log.info(q.toString()); - - ResultSet rs = s.execute(q); - - return null; + return objectToSave; } }); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (LinkageError e) { - e.printStackTrace(); - } finally {} - - return objectToSave; + } catch (EntityWriterException e) { + throw exceptionTranslator.translateExceptionIfPossible(new RuntimeException("Failed to translate Object to Query", e)); + } + } /** diff --git a/src/main/java/org/springframework/data/cassandra/core/RowCallback.java b/src/main/java/org/springframework/data/cassandra/core/RowCallback.java new file mode 100644 index 000000000..464ccaa41 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/RowCallback.java @@ -0,0 +1,22 @@ +/** + * 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 12, 2013 + */ +package org.springframework.data.cassandra.core; + +import com.datastax.driver.core.Row; + +/** + * Simple internal callback to allow operations on a {@link Row}. + * + * @author Alex Shvid + */ + +public interface RowCallback { + + T doWith(Row object); +} diff --git a/src/main/java/org/springframework/data/cassandra/exception/EntityWriterException.java b/src/main/java/org/springframework/data/cassandra/exception/EntityWriterException.java new file mode 100644 index 000000000..e7a50247c --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/exception/EntityWriterException.java @@ -0,0 +1,41 @@ +/** + * 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 12, 2013 + */ +package org.springframework.data.cassandra.exception; + +/** + * Exception to handle failing to write a PersistedEntity to a CQL String or Query object + * + * @author David Webb (dwebb@brightmove.com) + * + */ +public class EntityWriterException extends Exception { + + /** + * @param message + */ + public EntityWriterException(String message) { + super(message); + } + + /** + * @param cause + */ + public EntityWriterException(Throwable cause) { + super(cause); + } + + /** + * @param message + * @param cause + */ + public EntityWriterException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/src/main/java/org/springframework/data/cassandra/util/CQLUtils.java b/src/main/java/org/springframework/data/cassandra/util/CQLUtils.java index d0e373a99..cd4b0959d 100644 --- a/src/main/java/org/springframework/data/cassandra/util/CQLUtils.java +++ b/src/main/java/org/springframework/data/cassandra/util/CQLUtils.java @@ -7,9 +7,12 @@ import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.cassandra.exception.EntityWriterException; import org.springframework.data.cassandra.mapping.CassandraPersistentEntity; import org.springframework.data.cassandra.mapping.CassandraPersistentProperty; import org.springframework.data.mapping.PropertyHandler; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.util.ClassUtils; import com.datastax.driver.core.ColumnMetadata; import com.datastax.driver.core.DataType; @@ -31,6 +34,13 @@ public abstract class CQLUtils { private static Logger log = LoggerFactory.getLogger(CQLUtils.class); + /** + * Generates the CQL String to create a table in Cassandra + * + * @param tableName + * @param entity + * @return The CQL that can be passed to session.execute() + */ public static String createTable(String tableName, final CassandraPersistentEntity entity) { final StringBuilder str = new StringBuilder(); @@ -101,6 +111,13 @@ public abstract class CQLUtils { return str.toString(); } + /** + * Create the List of CQL for the indexes required for Cassandra mapped Table. + * + * @param tableName + * @param entity + * @return The list of CQL statements to run with session.execute() + */ public static List createIndexes(final String tableName, final CassandraPersistentEntity entity) { final List result = new ArrayList(); @@ -126,6 +143,14 @@ public abstract class CQLUtils { return result; } + /** + * Alter the table to refelct the entity annotations + * + * @param tableName + * @param entity + * @param table + * @return + */ public static List alterTable(final String tableName, final CassandraPersistentEntity entity, final TableMetadata table) { final List result = new ArrayList(); @@ -171,9 +196,24 @@ public abstract class CQLUtils { return result; } - public static Query toInsertQuery(String keyspaceName, String tableName, final CassandraPersistentEntity entity, final Object objectToSave) { + /** + * Generates a Query Object for an insert + * + * @param keyspaceName + * @param tableName + * @param entity + * @param objectToSave + * @param mappingContext + * @param beanClassLoader + * + * @return The Query object to run with session.execute(); + * @throws EntityWriterException + */ + public static Query toInsertQuery(String keyspaceName, String tableName, + final Object objectToSave, CassandraPersistentEntity entity) throws EntityWriterException { final Insert q = QueryBuilder.insertInto(keyspaceName, tableName); + final Exception innerException = new Exception(); entity.doWithProperties(new PropertyHandler() { public void doWithPersistentProperty(CassandraPersistentProperty prop) { @@ -191,15 +231,19 @@ public abstract class CQLUtils { } } catch (IllegalAccessException e) { - e.printStackTrace(); + innerException.initCause(e); } catch (IllegalArgumentException e) { - e.printStackTrace(); + innerException.initCause(e); } catch (InvocationTargetException e) { - e.printStackTrace(); + innerException.initCause(e); } } }); + if (innerException.getCause() != null) { + throw new EntityWriterException("Failed to convert Persistent Entity to CQL/Query", innerException.getCause()); + } + return q; } diff --git a/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java b/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java index 81818c2bb..4fdc8ef8d 100644 --- a/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java +++ b/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java @@ -89,8 +89,17 @@ public class CassandraOperationsTest { } } + /** + * This test inserts and selects users from the test.users table + * This is testing the CassandraTemplate: + *
    + *
  • insert()
  • + *
  • selectOne()
  • + *
  • select()
  • + *
+ */ @Test - public void insertTest() { + public void UsersTest() { User u = new User(); u.setUsername("cassandra"); @@ -99,6 +108,20 @@ public class CassandraOperationsTest { 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 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()); + } + } @After