Merge branch 'master' of https://github.com/shvid/spring-data-cassandra.git
This commit is contained in:
@@ -22,7 +22,6 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.cassandra.core.CassandraOperations;
|
||||
import org.springframework.cassandra.core.CassandraTemplate;
|
||||
import org.springframework.data.cassandra.core.SpringDataKeyspace;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -32,6 +31,7 @@ import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
|
||||
import org.springframework.data.cassandra.core.CassandraAdminOperations;
|
||||
import org.springframework.data.cassandra.core.CassandraAdminTemplate;
|
||||
import org.springframework.data.cassandra.core.SpringDataKeyspace;
|
||||
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
@@ -74,8 +74,8 @@ public abstract class AbstractCassandraConfiguration implements BeanClassLoaderA
|
||||
public abstract Cluster cluster() throws Exception;
|
||||
|
||||
/**
|
||||
* Creates a {@link Session} to be used by the {@link SpringDataKeyspace}. Will use the {@link Cluster} instance configured in
|
||||
* {@link #cluster()}.
|
||||
* Creates a {@link Session} to be used by the {@link SpringDataKeyspace}. Will use the {@link Cluster} instance
|
||||
* configured in {@link #cluster()}.
|
||||
*
|
||||
* @see #cluster()
|
||||
* @see #Keyspace()
|
||||
@@ -93,8 +93,8 @@ public abstract class AbstractCassandraConfiguration implements BeanClassLoaderA
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SpringDataKeyspace} to be used by the {@link CassandraTemplate}. Will use the {@link Session} instance
|
||||
* configured in {@link #session()} and {@link CassandraConverter} configured in {@link #converter()}.
|
||||
* Creates a {@link SpringDataKeyspace} to be used by the {@link CassandraTemplate}. Will use the {@link Session}
|
||||
* instance configured in {@link #session()} and {@link CassandraConverter} configured in {@link #converter()}.
|
||||
*
|
||||
* @see #cluster()
|
||||
* @see #Keyspace()
|
||||
|
||||
@@ -83,7 +83,7 @@ public class CassandraAdminTemplate implements CassandraAdminOperations {
|
||||
execute(new SessionCallback<Object>() {
|
||||
public Object doInSession(Session s) throws DataAccessException {
|
||||
|
||||
String cql = CqlUtils.createTable(tableName, entity);
|
||||
String cql = CqlUtils.createTable(tableName, entity, mappingContext);
|
||||
log.info("CREATE TABLE CQL -> " + cql);
|
||||
s.execute(cql);
|
||||
return null;
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.data.cassandra.core.SpringDataKeyspace;
|
||||
import org.springframework.cassandra.support.CassandraExceptionTranslator;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
@@ -250,7 +249,7 @@ public class CassandraKeyspaceFactoryBean implements FactoryBean<SpringDataKeysp
|
||||
|
||||
private void createNewTable(Session session, String useTableName, CassandraPersistentEntity<?> entity)
|
||||
throws NoHostAvailableException {
|
||||
String cql = CqlUtils.createTable(useTableName, entity);
|
||||
String cql = CqlUtils.createTable(useTableName, entity, mappingContext);
|
||||
log.info("Execute on keyspace " + keyspace + " CQL " + cql);
|
||||
session.execute(cql);
|
||||
for (String indexCQL : CqlUtils.createIndexes(useTableName, entity)) {
|
||||
|
||||
@@ -104,14 +104,6 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
|
||||
*/
|
||||
public int compare(CassandraPersistentProperty o1, CassandraPersistentProperty o2) {
|
||||
|
||||
if (o1.isColumnId()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (o2.isColumnId()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return o1.getColumnName().compareTo(o2.getColumnName());
|
||||
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
}
|
||||
|
||||
/**
|
||||
* Also considers fields that has a RowId annotation.
|
||||
* Also considers fields that has an Id annotation.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
@@ -61,16 +61,18 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
return true;
|
||||
}
|
||||
|
||||
return getField().isAnnotationPresent(RowId.class);
|
||||
return getField().isAnnotationPresent(Id.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* For dynamic tables returns true if property value is used as column name.
|
||||
* Returns the true if the field composite primary key.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isColumnId() {
|
||||
return getField().isAnnotationPresent(ColumnId.class);
|
||||
@Override
|
||||
public boolean isCompositePrimaryKey() {
|
||||
Class<?> fieldType = getField().getType();
|
||||
return fieldType.isAnnotationPresent(CompositePrimaryKey.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +148,16 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
* @return
|
||||
*/
|
||||
public boolean isIndexed() {
|
||||
return getField().isAnnotationPresent(Index.class);
|
||||
return getField().isAnnotationPresent(Indexed.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the property has Partitioned annotation on this column.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isPartitioned() {
|
||||
return getField().isAnnotationPresent(Partitioned.class);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -28,9 +28,9 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
public class CachingCassandraPersistentProperty extends BasicCassandraPersistentProperty {
|
||||
|
||||
private Boolean isIdProperty;
|
||||
private Boolean isColumnId;
|
||||
private String columnName;
|
||||
private Boolean isIndexed;
|
||||
private Boolean isPartitioned;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CachingCassandraPersistentProperty}.
|
||||
@@ -59,20 +59,6 @@ public class CachingCassandraPersistentProperty extends BasicCassandraPersistent
|
||||
return this.isIdProperty;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#isColumnId()
|
||||
*/
|
||||
@Override
|
||||
public boolean isColumnId() {
|
||||
|
||||
if (this.isColumnId == null) {
|
||||
this.isColumnId = super.isColumnId();
|
||||
}
|
||||
|
||||
return this.isColumnId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#getFieldName()
|
||||
@@ -100,4 +86,19 @@ public class CachingCassandraPersistentProperty extends BasicCassandraPersistent
|
||||
|
||||
return this.isIndexed;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#isPartitioned()
|
||||
*/
|
||||
@Override
|
||||
public boolean isPartitioned() {
|
||||
|
||||
if (this.isPartitioned == null) {
|
||||
this.isPartitioned = super.isPartitioned();
|
||||
}
|
||||
|
||||
return this.isPartitioned;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,11 +27,11 @@ import com.datastax.driver.core.DataType;
|
||||
public interface CassandraPersistentProperty extends PersistentProperty<CassandraPersistentProperty> {
|
||||
|
||||
/**
|
||||
* For dynamic tables returns true if property value is used as column name.
|
||||
* Returns the true if the field composite primary key.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isColumnId();
|
||||
boolean isCompositePrimaryKey();
|
||||
|
||||
/**
|
||||
* Returns the name of the field a property is persisted to.
|
||||
@@ -54,4 +54,11 @@ public interface CassandraPersistentProperty extends PersistentProperty<Cassandr
|
||||
*/
|
||||
boolean isIndexed();
|
||||
|
||||
/**
|
||||
* Returns true if the property has Partitioned annotation.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isPartitioned();
|
||||
|
||||
}
|
||||
|
||||
@@ -16,29 +16,26 @@
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
* Identifies composite row ID in the Cassandra table that contains several fields. Same as
|
||||
* @org.springframework.data.annotation.Id
|
||||
* Defines composite primary key class in the Cassandra table that contains several fields. Example:
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* class AccountPK { String account; String region; }
|
||||
* @CompositePrimaryKey class AccountPK { String account; String region; }
|
||||
*
|
||||
* @Table class Account {
|
||||
* @CompositeRowId Account pk; }
|
||||
* @Id AccountPK pk; }
|
||||
*
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Id
|
||||
public @interface CompositeRowId {
|
||||
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
public @interface CompositePrimaryKey {
|
||||
|
||||
}
|
||||
@@ -21,13 +21,12 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Uses in dynamic tables where column names are values of this field. Usually it is a Date/Time field or UUIDTime
|
||||
* field.
|
||||
* Identifies primary key or ID in the Cassandra table. Same as @org.springframework.data.annotation.Id
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
public @interface ColumnId {
|
||||
|
||||
@org.springframework.data.annotation.Id
|
||||
public @interface Id {
|
||||
}
|
||||
@@ -30,6 +30,6 @@ import java.lang.annotation.Target;
|
||||
*/
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
public @interface Index {
|
||||
public @interface Indexed {
|
||||
|
||||
}
|
||||
@@ -20,15 +20,14 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
* Identifies row ID in the Cassandra table. Same as @org.springframework.data.annotation.Id
|
||||
* Identifies partition key in the Cassandra composite primary key class. Annotated column is the part of the Cassandra
|
||||
* Partition Key (former Row Id).
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Id
|
||||
public @interface RowId {
|
||||
public @interface Partitioned {
|
||||
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.cassandra.repository;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
@@ -26,4 +27,6 @@ import org.springframework.data.repository.CrudRepository;
|
||||
*/
|
||||
public interface CassandraRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
|
||||
|
||||
List<T> findByPartitionKey(ID id);
|
||||
|
||||
}
|
||||
|
||||
@@ -108,6 +108,20 @@ public class SimpleCassandraRepository<T, ID extends Serializable> implements Ca
|
||||
return cassandraDataTemplate.selectOne(select, entityInformation.getJavaType());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.repository.CassandraRepository#findByPartitionKey(java.io.Serializable)
|
||||
*/
|
||||
@Override
|
||||
public List<T> findByPartitionKey(ID id) {
|
||||
Assert.notNull(id, "The given id must not be null!");
|
||||
|
||||
Select select = QueryBuilder.select().all().from(entityInformation.getTableName());
|
||||
select.where(getIdClause(id));
|
||||
|
||||
return cassandraDataTemplate.select(select, entityInformation.getJavaType());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.CrudRepository#exists(java.io.Serializable)
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.convert.EntityWriter;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
|
||||
import com.datastax.driver.core.ColumnMetadata;
|
||||
import com.datastax.driver.core.DataType;
|
||||
@@ -48,66 +49,95 @@ public abstract class CqlUtils {
|
||||
* @param entity
|
||||
* @return The CQL that can be passed to session.execute()
|
||||
*/
|
||||
public static String createTable(String tableName, final CassandraPersistentEntity<?> entity) {
|
||||
public static String createTable(String tableName, final CassandraPersistentEntity<?> entity,
|
||||
final MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext) {
|
||||
|
||||
final StringBuilder str = new StringBuilder();
|
||||
str.append("CREATE TABLE ");
|
||||
str.append(tableName);
|
||||
str.append('(');
|
||||
|
||||
final List<String> ids = new ArrayList<String>();
|
||||
final List<String> idColumns = new ArrayList<String>();
|
||||
final List<String> clusteredIds = new ArrayList<String>();
|
||||
final List<String> partitionedIds = new ArrayList<String>();
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
|
||||
|
||||
if (str.charAt(str.length() - 1) != '(') {
|
||||
str.append(',');
|
||||
}
|
||||
if (prop.isCompositePrimaryKey()) {
|
||||
|
||||
String columnName = prop.getColumnName();
|
||||
CassandraPersistentEntity<?> pkEntity = mappingContext.getPersistentEntity(prop.getRawType());
|
||||
|
||||
str.append(columnName);
|
||||
str.append(' ');
|
||||
pkEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty pkProp) {
|
||||
|
||||
DataType dataType = prop.getDataType();
|
||||
if (pkProp.isPartitioned()) {
|
||||
partitionedIds.add(pkProp.getColumnName());
|
||||
} else {
|
||||
clusteredIds.add(pkProp.getColumnName());
|
||||
}
|
||||
|
||||
str.append(toCQL(dataType));
|
||||
if (str.charAt(str.length() - 1) != '(') {
|
||||
str.append(',');
|
||||
}
|
||||
|
||||
if (prop.isIdProperty()) {
|
||||
ids.add(prop.getColumnName());
|
||||
}
|
||||
String columnName = pkProp.getColumnName();
|
||||
|
||||
if (prop.isColumnId()) {
|
||||
idColumns.add(prop.getColumnName());
|
||||
str.append(columnName);
|
||||
str.append(' ');
|
||||
|
||||
DataType dataType = pkProp.getDataType();
|
||||
|
||||
str.append(toCQL(dataType));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
if (str.charAt(str.length() - 1) != '(') {
|
||||
str.append(',');
|
||||
}
|
||||
|
||||
String columnName = prop.getColumnName();
|
||||
|
||||
str.append(columnName);
|
||||
str.append(' ');
|
||||
|
||||
DataType dataType = prop.getDataType();
|
||||
|
||||
str.append(toCQL(dataType));
|
||||
|
||||
if (prop.isIdProperty()) {
|
||||
partitionedIds.add(prop.getColumnName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (ids.isEmpty()) {
|
||||
throw new InvalidDataAccessApiUsageException("not found primary ID in the entity " + entity.getType());
|
||||
if (partitionedIds.isEmpty()) {
|
||||
throw new InvalidDataAccessApiUsageException("not found partition key in the entity " + entity.getType());
|
||||
}
|
||||
|
||||
str.append(",PRIMARY KEY(");
|
||||
|
||||
// if (ids.size() > 1) {
|
||||
// str.append('(');
|
||||
// }
|
||||
if (partitionedIds.size() > 1) {
|
||||
str.append('(');
|
||||
}
|
||||
|
||||
for (String id : ids) {
|
||||
for (String id : partitionedIds) {
|
||||
if (str.charAt(str.length() - 1) != '(') {
|
||||
str.append(',');
|
||||
}
|
||||
str.append(id);
|
||||
}
|
||||
|
||||
// if (ids.size() > 1) {
|
||||
// str.append(')');
|
||||
// }
|
||||
if (partitionedIds.size() > 1) {
|
||||
str.append(')');
|
||||
}
|
||||
|
||||
for (String id : idColumns) {
|
||||
for (String id : clusteredIds) {
|
||||
str.append(',');
|
||||
str.append(id);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.springframework.data.cassandra.mapping.BasicCassandraPersistentProper
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.mapping.Column;
|
||||
import org.springframework.data.cassandra.mapping.ColumnId;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -81,12 +80,6 @@ public class BasicCassandraPersistentPropertyIntegrationTests {
|
||||
assertThat(getPropertyFor(field).getColumnName(), is("time"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checksColumnIdProperty() {
|
||||
CassandraPersistentProperty property = getPropertyFor(ReflectionUtils.findField(Timeline.class, "time"));
|
||||
assertThat(property.isColumnId(), is(true));
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearCassandra() {
|
||||
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
|
||||
@@ -106,7 +99,6 @@ public class BasicCassandraPersistentPropertyIntegrationTests {
|
||||
@Id
|
||||
String id;
|
||||
|
||||
@ColumnId
|
||||
Date time;
|
||||
|
||||
@Column("message")
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.test.integration.table;
|
||||
|
||||
import org.springframework.data.cassandra.mapping.RowId;
|
||||
import org.springframework.data.cassandra.mapping.Id;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
/**
|
||||
@@ -27,7 +27,7 @@ import org.springframework.data.cassandra.mapping.Table;
|
||||
@Table(name = "book")
|
||||
public class Book {
|
||||
|
||||
@RowId
|
||||
@Id
|
||||
private String isbn;
|
||||
|
||||
private String title;
|
||||
|
||||
@@ -18,19 +18,15 @@ package org.springframework.data.cassandra.test.integration.table;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.ColumnId;
|
||||
import org.springframework.data.cassandra.mapping.Id;
|
||||
import org.springframework.data.cassandra.mapping.Qualify;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* This is an example of dynamic table that creates each time new column with Post timestamp annotated by @ColumnId.
|
||||
*
|
||||
* It is possible to use a static table for posts and identify them by PostId(UUID), but in this case we need to use
|
||||
* MapReduce for Big Data to find posts for particular user, so it is better to have index (userId) -> index (post time)
|
||||
* architecture. It helps a lot to build eventually a search index for the particular user.
|
||||
* This is an example of dynamic table (wide row). PartitionKey (former RowId) is pk.author. ClusteredColumn (former
|
||||
* Column Id) is pk.time
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@@ -38,17 +34,10 @@ import com.datastax.driver.core.DataType;
|
||||
public class Comment {
|
||||
|
||||
/*
|
||||
* Primary Row ID
|
||||
* Primary Key
|
||||
*/
|
||||
@Id
|
||||
private String author;
|
||||
|
||||
/*
|
||||
* Column ID
|
||||
*/
|
||||
@ColumnId
|
||||
@Qualify(type = DataType.Name.TIMESTAMP)
|
||||
private Date time;
|
||||
private CommentPK pk;
|
||||
|
||||
private String text;
|
||||
|
||||
@@ -61,20 +50,12 @@ public class Comment {
|
||||
private String postAuthor;
|
||||
private Date postTime;
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
public CommentPK getPk() {
|
||||
return pk;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
public void setPk(CommentPK pk) {
|
||||
this.pk = pk;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.springframework.data.cassandra.test.integration.table;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.data.cassandra.mapping.CompositePrimaryKey;
|
||||
import org.springframework.data.cassandra.mapping.Partitioned;
|
||||
import org.springframework.data.cassandra.mapping.Qualify;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* This is an example of dynamic table (wide row) that creates each time new column with timestamp.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
@CompositePrimaryKey
|
||||
public class CommentPK {
|
||||
|
||||
/*
|
||||
* Row ID
|
||||
*/
|
||||
@Partitioned
|
||||
private String author;
|
||||
|
||||
/*
|
||||
* Clustered Column
|
||||
*/
|
||||
@Qualify(type = DataType.Name.TIMESTAMP)
|
||||
private Date time;
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,17 +17,12 @@ package org.springframework.data.cassandra.test.integration.table;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.Column;
|
||||
import org.springframework.data.cassandra.mapping.RowId;
|
||||
import org.springframework.data.cassandra.mapping.Id;
|
||||
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.
|
||||
* This is an example of the LogEntry static table, where all fields are columns in Cassandra row.
|
||||
*
|
||||
* User contains base information related for separate user, like names, additional information, emails, following
|
||||
* users, friends.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@@ -35,9 +30,9 @@ import org.springframework.data.cassandra.mapping.Table;
|
||||
public class LogEntry {
|
||||
|
||||
/*
|
||||
* Primary Row ID
|
||||
* Primary Key
|
||||
*/
|
||||
@RowId
|
||||
@Id
|
||||
private Date logDate;
|
||||
|
||||
private String hostname;
|
||||
|
||||
@@ -18,13 +18,11 @@ package org.springframework.data.cassandra.test.integration.table;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.ColumnId;
|
||||
import org.springframework.data.cassandra.mapping.Index;
|
||||
import org.springframework.data.cassandra.mapping.Indexed;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
/**
|
||||
* This is an example of dynamic table that creates each time new column with Notification timestamp annotated by
|
||||
* @ColumnId.
|
||||
* This is an example of dynamic table that creates each time new column with Notification timestamp.
|
||||
*
|
||||
* By default it is active Notification until user deactivate it. This table uses index on the field active to access in
|
||||
* WHERE cause only for active notifications.
|
||||
@@ -35,18 +33,12 @@ import org.springframework.data.cassandra.mapping.Table;
|
||||
public class Notification {
|
||||
|
||||
/*
|
||||
* Primary Row ID
|
||||
* Primary Key
|
||||
*/
|
||||
@Id
|
||||
private String username;
|
||||
private NotificationPK pk;
|
||||
|
||||
/*
|
||||
* Column ID
|
||||
*/
|
||||
@ColumnId
|
||||
private Date time;
|
||||
|
||||
@Index
|
||||
@Indexed
|
||||
private boolean active;
|
||||
|
||||
/*
|
||||
@@ -57,20 +49,12 @@ public class Notification {
|
||||
private String refAuthor;
|
||||
private Date refTime;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
public NotificationPK getPk() {
|
||||
return pk;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
public void setPk(NotificationPK pk) {
|
||||
this.pk = pk;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.integration.table;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.data.cassandra.mapping.CompositePrimaryKey;
|
||||
import org.springframework.data.cassandra.mapping.Partitioned;
|
||||
import org.springframework.data.cassandra.mapping.Qualify;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* This is an example of dynamic table that creates each time new column with Notification timestamp.
|
||||
*
|
||||
* By default it is active Notification until user deactivate it. This table uses index on the field active to access in
|
||||
* WHERE cause only for active notifications.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
@CompositePrimaryKey
|
||||
public class NotificationPK {
|
||||
|
||||
/*
|
||||
* Row ID
|
||||
*/
|
||||
@Partitioned
|
||||
private String username;
|
||||
|
||||
/*
|
||||
* Clustered Column
|
||||
*/
|
||||
@Qualify(type = DataType.Name.TIMESTAMP)
|
||||
private Date time;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,11 +20,10 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.ColumnId;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
/**
|
||||
* This is an example of dynamic table that creates each time new column with Post timestamp annotated by @ColumnId.
|
||||
* This is an example of dynamic table that creates each time new column with Post timestamp.
|
||||
*
|
||||
* It is possible to use a static table for posts and identify them by PostId(UUID), but in this case we need to use
|
||||
* MapReduce for Big Data to find posts for particular user, so it is better to have index (userId) -> index (post time)
|
||||
@@ -36,16 +35,10 @@ import org.springframework.data.cassandra.mapping.Table;
|
||||
public class Post {
|
||||
|
||||
/*
|
||||
* Primary Row ID
|
||||
* Primary Key
|
||||
*/
|
||||
@Id
|
||||
private String author;
|
||||
|
||||
/*
|
||||
* Column ID
|
||||
*/
|
||||
@ColumnId
|
||||
private Date time;
|
||||
private PostPK pk;
|
||||
|
||||
private String type; // status, share
|
||||
|
||||
@@ -55,20 +48,12 @@ public class Post {
|
||||
private Set<String> likes;
|
||||
private Set<String> followers;
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
public PostPK getPk() {
|
||||
return pk;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
public void setPk(PostPK pk) {
|
||||
this.pk = pk;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.integration.table;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.data.cassandra.mapping.CompositePrimaryKey;
|
||||
import org.springframework.data.cassandra.mapping.Partitioned;
|
||||
|
||||
/**
|
||||
* This is an example of dynamic table that creates each time new column with Post timestamp.
|
||||
*
|
||||
* It is possible to use a static table for posts and identify them by PostId(UUID), but in this case we need to use
|
||||
* MapReduce for Big Data to find posts for particular user, so it is better to have index (userId) -> index (post time)
|
||||
* architecture. It helps a lot to build eventually a search index for the particular user.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
@CompositePrimaryKey
|
||||
public class PostPK {
|
||||
|
||||
/*
|
||||
* Row ID
|
||||
*/
|
||||
@Partitioned
|
||||
private String author;
|
||||
|
||||
/*
|
||||
* Clustered Column
|
||||
*/
|
||||
private Date time;
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.cassandra.test.integration.table;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.ColumnId;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
/**
|
||||
@@ -34,16 +33,10 @@ import org.springframework.data.cassandra.mapping.Table;
|
||||
public class Timeline {
|
||||
|
||||
/*
|
||||
* Primary Row ID
|
||||
* Row ID
|
||||
*/
|
||||
@Id
|
||||
private String username;
|
||||
|
||||
/*
|
||||
* Column ID
|
||||
*/
|
||||
@ColumnId
|
||||
private Date time;
|
||||
private TimelinePK pk;
|
||||
|
||||
/*
|
||||
* Reference to the post by author and postUID
|
||||
@@ -51,20 +44,12 @@ public class Timeline {
|
||||
private String author;
|
||||
private Date postTime;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
public TimelinePK getPk() {
|
||||
return pk;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
public void setPk(TimelinePK pk) {
|
||||
this.pk = pk;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.integration.table;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.data.cassandra.mapping.CompositePrimaryKey;
|
||||
import org.springframework.data.cassandra.mapping.Partitioned;
|
||||
|
||||
/**
|
||||
* This is an example of the users timeline dynamic table, where all columns are dynamically created by @ColumnId field
|
||||
* value. The rest fields are places in Cassandra value.
|
||||
*
|
||||
* Timeline entity is used to store user's status updates that it follows in the site. Timeline always ordered by @ColumnId
|
||||
* field and we can retrieve last top status updates by using limits.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
@CompositePrimaryKey
|
||||
public class TimelinePK {
|
||||
|
||||
/*
|
||||
* Row ID
|
||||
*/
|
||||
@Partitioned
|
||||
private String username;
|
||||
|
||||
/*
|
||||
* Clustered Column
|
||||
*/
|
||||
private Date time;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,7 @@ package org.springframework.data.cassandra.test.integration.table;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.mapping.Index;
|
||||
import org.springframework.data.cassandra.mapping.Indexed;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ public class User {
|
||||
* Secondary index, used only on fields with common information,
|
||||
* not effective on email, username
|
||||
*/
|
||||
@Index
|
||||
@Indexed
|
||||
private String place;
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* 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.integration.table;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user