This commit is contained in:
Matthew Adams
2013-12-09 10:11:49 -06:00
parent 46a7b9c131
commit 91025be1d2
17 changed files with 127 additions and 134 deletions

View File

@@ -275,7 +275,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
pkEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
public void doWithPersistentProperty(CassandraPersistentProperty pkProp) {
if (pkProp.isPartitioned()) {
if (pkProp.isPartitionKeyColumn()) {
spec.partitionKeyColumn(pkProp.getColumnName(), pkProp.getDataType());
} else {
spec.clusteredKeyColumn(pkProp.getColumnName(), pkProp.getDataType(), pkProp.getOrdering());

View File

@@ -21,6 +21,7 @@ import java.util.List;
import java.util.Set;
import org.springframework.cassandra.core.Ordering;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
@@ -51,10 +52,6 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
super(field, propertyDescriptor, owner, simpleTypeHolder);
}
/**
* Also considers fields that has an Id annotation.
*
*/
@Override
public boolean isIdProperty() {
@@ -62,48 +59,40 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
return true;
}
return getField().isAnnotationPresent(Id.class);
return getField().isAnnotationPresent(PrimaryKey.class);
}
/**
* Returns the true if the field composite primary key.
*
* @return
*/
@Override
public boolean isCompositePrimaryKey() {
Class<?> fieldType = getField().getType();
return fieldType.isAnnotationPresent(CompositePrimaryKey.class);
return getField().getType().isAnnotationPresent(CompositePrimaryKey.class);
}
/**
* Returns the column name to be used to store the value of the property inside the Cassandra.
*
* @return
*/
public String getColumnName() {
// first check @Column annotation
Column annotation = getField().getAnnotation(Column.class);
return annotation != null && StringUtils.hasText(annotation.value()) ? annotation.value() : field.getName();
if (annotation != null && StringUtils.hasText(annotation.value())) {
return annotation.value();
}
// else check @KeyColumn annotation
PrimaryKeyColumn anno = getField().getAnnotation(PrimaryKeyColumn.class);
if (anno == null || !StringUtils.hasText(anno.value())) {
return field.getName();
}
return anno.value();
}
/**
* Returns ordering for the column. Valid only for clustered columns.
*
* @return
*/
public Ordering getOrdering() {
Order annotation = getField().getAnnotation(Order.class);
return annotation != null ? annotation.value() : null;
PrimaryKeyColumn anno = getField().getAnnotation(PrimaryKeyColumn.class);
return anno == null ? null : anno.ordering();
}
/**
* Returns the data type information if exists.
*
* @return
*/
public DataType getDataType() {
Qualify annotation = getField().getAnnotation(Qualify.class);
if (annotation != null && annotation.type() != null) {
if (annotation != null) {
return qualifyAnnotatedType(annotation);
}
if (isMap()) {
@@ -153,28 +142,30 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
}
}
/**
* Returns true if the property has secondary index on this column.
*
* @return
*/
public boolean isIndexed() {
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);
public boolean isPartitionKeyColumn() {
PrimaryKeyColumn anno = getField().getAnnotation(PrimaryKeyColumn.class);
return anno != null && anno.type() == PrimaryKeyType.PARTITIONED;
}
@Override
public boolean isClusterKeyColumn() {
PrimaryKeyColumn anno = getField().getAnnotation(PrimaryKeyColumn.class);
return anno != null && anno.type() == PrimaryKeyType.CLUSTERED;
}
@Override
public boolean isPrimaryKeyColumn() {
return getField().isAnnotationPresent(PrimaryKeyColumn.class);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.AbstractPersistentProperty#createAssociation()
*/
@Override
protected Association<CassandraPersistentProperty> createAssociation() {
return new Association<CassandraPersistentProperty>(this, null);
@@ -206,5 +197,4 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
+ this.getName() + "' type is '" + this.getType() + "' in the entity " + this.getOwner().getName());
}
}
}

View File

@@ -92,10 +92,10 @@ public class CachingCassandraPersistentProperty extends BasicCassandraPersistent
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#isPartitioned()
*/
@Override
public boolean isPartitioned() {
public boolean isPartitionKeyColumn() {
if (this.isPartitioned == null) {
this.isPartitioned = super.isPartitioned();
this.isPartitioned = super.isPartitionKeyColumn();
}
return this.isPartitioned;

View File

@@ -24,49 +24,50 @@ import com.datastax.driver.core.DataType;
* Cassandra specific {@link org.springframework.data.mapping.PersistentProperty} extension.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public interface CassandraPersistentProperty extends PersistentProperty<CassandraPersistentProperty> {
/**
* Returns the true if the field composite primary key.
*
* @return
* Whether the property is a composite primary key.
*/
boolean isCompositePrimaryKey();
/**
* Returns the name of the field a property is persisted to.
*
* @return
* The name of the column to which a property is persisted.
*/
String getColumnName();
/**
* Returns ordering for the column. Valid only for clustered columns.
*
* @return
* The ordering for the column. Valid only for clustered columns.
*/
Ordering getOrdering();
/**
* Returns the data type.
*
* @return
* The column's data type.
*/
DataType getDataType();
/**
* Returns true if the property has secondary index on this column.
*
* @return
* Whether the property has secondary index on this column.
*/
boolean isIndexed();
/**
* Returns true if the property has Partitioned annotation.
*
* @return
* Whether the property is a partition key column.
*/
boolean isPartitioned();
boolean isPartitionKeyColumn();
/**
* Whether the property is a cluster key column.
*/
boolean isClusterKeyColumn();
/**
* Whether the property is a partition key column or a cluster key column
*
* @see #isPartitionKeyColumn()
* @see #isClusterKeyColumn()
*/
boolean isPrimaryKeyColumn();
}

View File

@@ -53,16 +53,22 @@ public class CassandraSimpleTypes {
primitiveWrapperTypeMap.put(Short.class, short.class);
Set<Class<?>> simpleTypes = new HashSet<Class<?>>();
for (DataType dataType : DataType.allPrimitiveTypes()) {
simpleTypes.add(dataType.asJavaClass());
Class<?> javaClass = dataType.asJavaClass();
simpleTypes.add(javaClass);
javaClassToDataType.put(javaClass, dataType);
Class<?> primitiveJavaClass = primitiveWrapperTypeMap.get(javaClass);
if (primitiveJavaClass != null) {
javaClassToDataType.put(primitiveJavaClass, dataType);
}
nameToDataType.put(dataType.getName(), dataType);
}
javaClassToDataType.put(String.class, DataType.text());
CASSANDRA_SIMPLE_TYPES = Collections.unmodifiableSet(simpleTypes);
}

View File

@@ -38,6 +38,7 @@ import java.lang.annotation.RetentionPolicy;
* Annotation to define custom metadata for document fields.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@@ -45,9 +46,6 @@ public @interface Column {
/**
* The name of the column in the table.
*
* @return
*/
String value() default "";
}

View File

@@ -31,11 +31,12 @@ import java.lang.annotation.Target;
*
*
* @author Alex Shvid
* @deprecated This class is actually unnecessary and can be inferred by the existence of field(s) with
* {@link PrimaryKeyColumn} annotations on them.
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
@Deprecated
public @interface CompositePrimaryKey {
}

View File

@@ -1,34 +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.mapping;
import org.springframework.cassandra.core.Ordering;
/**
* Annotation to define custom order for clustered column.
*
* @author Alex Shvid
*/
public @interface Order {
/**
* Ordering of the column in the table.
*
* @return
*/
Ordering value() default Ordering.ASCENDING;
}

View File

@@ -21,12 +21,14 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Identifies primary key or ID in the Cassandra table. Same as @org.springframework.data.annotation.Id
* Identifies the primary key field of the entity, which may be of a basic type or of a type that represents a composite
* primary key class. This field corresponds to the <code>PRIMARY KEY</code> of the corresponding Cassandra table.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@org.springframework.data.annotation.Id
public @interface Id {
public @interface PrimaryKey {
}

View File

@@ -20,14 +20,35 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.cassandra.core.Ordering;
import org.springframework.cassandra.core.PrimaryKeyType;
/**
* 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
* Identifies the annotated field of a composite primary key class as a primary key field that is either a partition or
* cluster key field.
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
public @interface Partitioned {
@Target(value = { ElementType.FIELD, ElementType.METHOD })
public @interface PrimaryKeyColumn {
/**
* The name of the column in the table.
*/
String value() default "";
/**
* The order of this column among all primary key columns.
*/
int ordinal();
/**
* The type of this key column. Default is {@link PrimaryKeyType#CLUSTERED}.
*/
PrimaryKeyType type() default PrimaryKeyType.CLUSTERED;
/**
* The cluster ordering of this column if {@link #type()} is {@link PrimaryKeyType#CLUSTERED}, otherwise ignored.
* Default is {@link Ordering#ASCENDING}.
*/
Ordering ordering() default Ordering.ASCENDING;
}

View File

@@ -15,7 +15,7 @@
*/
package org.springframework.data.cassandra.test.integration.table;
import org.springframework.data.cassandra.mapping.Id;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
/**
@@ -27,7 +27,7 @@ import org.springframework.data.cassandra.mapping.Table;
@Table(name = "book")
public class Book {
@Id
@PrimaryKey
private String isbn;
private String title;

View File

@@ -18,7 +18,7 @@ package org.springframework.data.cassandra.test.integration.table;
import java.util.Date;
import java.util.Set;
import org.springframework.data.cassandra.mapping.Id;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Qualify;
import org.springframework.data.cassandra.mapping.Table;
@@ -36,7 +36,7 @@ public class Comment {
/*
* Primary Key
*/
@Id
@PrimaryKey
private CommentPK pk;
private String text;

View File

@@ -1,5 +1,3 @@
package org.springframework.data.cassandra.test.integration.table;
/*
* Copyright 2010-2013 the original author or authors.
*
@@ -15,10 +13,13 @@ package org.springframework.data.cassandra.test.integration.table;
* 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.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.CompositePrimaryKey;
import org.springframework.data.cassandra.mapping.Partitioned;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Qualify;
import com.datastax.driver.core.DataType;
@@ -35,12 +36,13 @@ public class CommentPK {
/*
* Row ID
*/
@Partitioned
@PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String author;
/*
* Clustered Column
*/
@PrimaryKeyColumn(ordinal = 1)
@Qualify(type = DataType.Name.TIMESTAMP)
private Date time;

View File

@@ -17,7 +17,7 @@ package org.springframework.data.cassandra.test.integration.table;
import java.util.Date;
import org.springframework.data.cassandra.mapping.Id;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
/**
@@ -32,7 +32,7 @@ public class LogEntry {
/*
* Primary Key
*/
@Id
@PrimaryKey
private Date logDate;
private String hostname;

View File

@@ -17,8 +17,9 @@ package org.springframework.data.cassandra.test.integration.table;
import java.util.Date;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.CompositePrimaryKey;
import org.springframework.data.cassandra.mapping.Partitioned;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Qualify;
import com.datastax.driver.core.DataType;
@@ -37,12 +38,13 @@ public class NotificationPK {
/*
* Row ID
*/
@Partitioned
@PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String username;
/*
* Clustered Column
*/
@PrimaryKeyColumn(ordinal = 1)
@Qualify(type = DataType.Name.TIMESTAMP)
private Date time;

View File

@@ -17,8 +17,9 @@ package org.springframework.data.cassandra.test.integration.table;
import java.util.Date;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.CompositePrimaryKey;
import org.springframework.data.cassandra.mapping.Partitioned;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
/**
* This is an example of dynamic table that creates each time new column with Post timestamp.
@@ -36,12 +37,13 @@ public class PostPK {
/*
* Row ID
*/
@Partitioned
@PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String author;
/*
* Clustered Column
*/
@PrimaryKeyColumn(ordinal = 1)
private Date time;
public String getAuthor() {

View File

@@ -17,8 +17,9 @@ package org.springframework.data.cassandra.test.integration.table;
import java.util.Date;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.CompositePrimaryKey;
import org.springframework.data.cassandra.mapping.Partitioned;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
/**
* This is an example of the users timeline dynamic table, where all columns are dynamically created by @ColumnId field
@@ -36,12 +37,13 @@ public class TimelinePK {
/*
* Row ID
*/
@Partitioned
@PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String username;
/*
* Clustered Column
*/
@PrimaryKeyColumn(ordinal = 1)
private Date time;
public String getUsername() {