diff --git a/pom.xml b/pom.xml index 95797e1fa..6a52dc867 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,7 @@ Alex Shvid a at shvid.com + Project Lead Developer -8 diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraAdminTemplate.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraAdminTemplate.java index 77292e0d6..ad530226f 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraAdminTemplate.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraAdminTemplate.java @@ -28,7 +28,7 @@ import com.datastax.driver.core.TableMetadata; */ public class CassandraAdminTemplate implements CassandraAdminOperations { - private static Logger log = LoggerFactory.getLogger(CassandraAdminTemplate.class); + private static final Logger log = LoggerFactory.getLogger(CassandraAdminTemplate.class); private SpringDataKeyspace keyspace; private Session session; diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraDataOperations.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraDataOperations.java index 39a0722a8..4e0f8aecc 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraDataOperations.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraDataOperations.java @@ -50,6 +50,16 @@ public interface CassandraDataOperations { */ List select(String cql, Class selectClass); + /** + * Execute query and convert ResultSet to the list of entities + * + * @param selectQuery must not be {@literal null}. + * @param selectClass must not be {@literal null}, mapped entity type. + * @return + */ + + List select(Select selectQuery, Class selectClass); + /** * Execute query and convert ResultSet to the entity * @@ -59,12 +69,26 @@ public interface CassandraDataOperations { */ T selectOne(String cql, Class selectClass); - List select(Select selectQuery, Class selectClass); - T selectOne(Select selectQuery, Class selectClass); + /** + * Counts rows for given query + * + * @param selectQuery + * @return + */ + Long count(Select selectQuery); + /** + * Counts all rows for given table + * + * @param tableName + * @return + */ + + Long count(String tableName); + /** * Insert the given object to the table by id. * diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraDataTemplate.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraDataTemplate.java index 32e577a9b..eea7683a1 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraDataTemplate.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraDataTemplate.java @@ -18,7 +18,6 @@ package org.springframework.data.cassandra.core; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -43,6 +42,7 @@ import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.Session; import com.datastax.driver.core.querybuilder.Batch; +import com.datastax.driver.core.querybuilder.QueryBuilder; import com.datastax.driver.core.querybuilder.Select; /** @@ -123,13 +123,22 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#selectCount(com.datastax.driver.core.querybuilder.Select) + * @see org.springframework.data.cassandra.core.CassandraOperations#count(com.datastax.driver.core.querybuilder.Select) */ @Override public Long count(Select selectQuery) { return doSelectCount(selectQuery); } + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.CassandraOperations#count(java.lang.String) + */ + @Override + public Long count(String tableName) { + Select select = QueryBuilder.select().countAll().from(tableName); + return doSelectCount(select); + } + /* (non-Javadoc) * @see org.springframework.data.cassandra.core.CassandraOperations#delete(java.util.List) */ @@ -165,7 +174,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public void delete(List entities, String tableName) { - delete(entities, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + delete(entities, tableName, defaultOptions); } /* (non-Javadoc) @@ -223,7 +233,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public void delete(T entity, String tableName) { - delete(entity, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + delete(entity, tableName, defaultOptions); } /* (non-Javadoc) @@ -280,7 +291,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public void deleteAsynchronously(List entities, String tableName) { - insertAsynchronously(entities, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + insertAsynchronously(entities, tableName, defaultOptions); } /* (non-Javadoc) @@ -338,7 +350,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public void deleteAsynchronously(T entity, String tableName) { - deleteAsynchronously(entity, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + deleteAsynchronously(entity, tableName, defaultOptions); } /* (non-Javadoc) @@ -430,7 +443,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public List insert(List entities, String tableName) { - return insert(entities, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + return insert(entities, tableName, defaultOptions); } /* (non-Javadoc) @@ -488,7 +502,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public T insert(T entity, String tableName) { - return insert(entity, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + return insert(entity, tableName, defaultOptions); } /* (non-Javadoc) @@ -545,7 +560,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public List insertAsynchronously(List entities, String tableName) { - return insertAsynchronously(entities, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + return insertAsynchronously(entities, tableName, defaultOptions); } /* (non-Javadoc) @@ -603,7 +619,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public T insertAsynchronously(T entity, String tableName) { - return insertAsynchronously(entity, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + return insertAsynchronously(entity, tableName, defaultOptions); } /* (non-Javadoc) @@ -695,7 +712,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public List update(List entities, String tableName) { - return update(entities, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + return update(entities, tableName, defaultOptions); } /* (non-Javadoc) @@ -753,7 +771,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public T update(T entity, String tableName) { - return update(entity, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + return update(entity, tableName, defaultOptions); } /* (non-Javadoc) @@ -810,7 +829,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public List updateAsynchronously(List entities, String tableName) { - return updateAsynchronously(entities, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + return updateAsynchronously(entities, tableName, defaultOptions); } /* (non-Javadoc) @@ -868,7 +888,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ @Override public T updateAsynchronously(T entity, String tableName) { - return updateAsynchronously(entity, tableName, new HashMap()); + Map defaultOptions = Collections.emptyMap(); + return updateAsynchronously(entity, tableName, defaultOptions); } /* (non-Javadoc) @@ -968,6 +989,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ private T doSelectOne(final String query, ReadRowCallback readRowCallback) { + logger.info(query); + /* * Run the Query */ @@ -1183,6 +1206,7 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr try { final Query q = CqlUtils.toInsertQuery(keyspace, tableName, entity, optionsByName, cassandraConverter); + logger.info(q.toString()); if (q.getConsistencyLevel() != null) { logger.info(q.getConsistencyLevel().name()); diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoriesRegistrar.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoriesRegistrar.java new file mode 100644 index 000000000..ac9a1c13a --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoriesRegistrar.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012 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.repository.config; + +import java.lang.annotation.Annotation; + +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport; +import org.springframework.data.repository.config.RepositoryConfigurationExtension; + +/** + * {@link ImportBeanDefinitionRegistrar} to setup Cassandra repositories via {@link EnableCassandraRepositories}. + * + * @author Alex Shvid + * + */ +public class CassandraRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport { + + /* + * (non-Javadoc) + * + * @see org.springframework.data.repository.config. + * RepositoryBeanDefinitionRegistrarSupport#getAnnotation() + */ + @Override + protected Class getAnnotation() { + return EnableCassandraRepositories.class; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.data.repository.config. + * RepositoryBeanDefinitionRegistrarSupport#getExtension() + */ + @Override + protected RepositoryConfigurationExtension getExtension() { + return new CassandraRepositoryConfigurationExtension(); + } + +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoryConfigurationExtension.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoryConfigurationExtension.java new file mode 100644 index 000000000..35b4912b8 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoryConfigurationExtension.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012 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.repository.config; + +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.data.cassandra.repository.support.CassandraRepositoryFactoryBean; +import org.springframework.data.config.ParsingUtils; +import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource; +import org.springframework.data.repository.config.RepositoryConfigurationExtension; +import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport; +import org.springframework.data.repository.config.XmlRepositoryConfigurationSource; +import org.springframework.util.StringUtils; +import org.w3c.dom.Element; + +/** + * {@link RepositoryConfigurationExtension} for Cassandra. + * + * @author Alex Shvid + * + */ +public class CassandraRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport { + + private static final String CASSANDRA_DATA_TEMPLATE_REF = "cassandra-data-template-ref"; + private static final String CREATE_QUERY_INDEXES = "create-query-indexes"; + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getModulePrefix() + */ + @Override + protected String getModulePrefix() { + return "cassandra"; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryConfigurationExtension#getRepositoryFactoryClassName() + */ + public String getRepositoryFactoryClassName() { + return CassandraRepositoryFactoryBean.class.getName(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.XmlRepositoryConfigurationSource) + */ + @Override + public void postProcess(BeanDefinitionBuilder builder, XmlRepositoryConfigurationSource config) { + + Element element = config.getElement(); + + ParsingUtils.setPropertyReference(builder, element, CASSANDRA_DATA_TEMPLATE_REF, "cassandraDataTemplate"); + ParsingUtils.setPropertyValue(builder, element, CREATE_QUERY_INDEXES, "createIndexesForQueryMethods"); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource) + */ + @Override + public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfigurationSource config) { + + AnnotationAttributes attributes = config.getAttributes(); + + String cassandraDataTemplateRef = attributes.getString("cassandraDataTemplateRef"); + if (StringUtils.hasText(cassandraDataTemplateRef)) { + builder.addPropertyReference("cassandraDataTemplate", cassandraDataTemplateRef); + } + builder.addPropertyValue("createIndexesForQueryMethods", attributes.getBoolean("createIndexesForQueryMethods")); + } + +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/EnableCassandraRepositories.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/EnableCassandraRepositories.java new file mode 100644 index 000000000..26a471b7a --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/EnableCassandraRepositories.java @@ -0,0 +1,125 @@ +/* + * Copyright 2012 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.repository.config; + +import java.lang.annotation.Documented; +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.beans.factory.FactoryBean; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Import; +import org.springframework.data.cassandra.core.CassandraDataTemplate; +import org.springframework.data.cassandra.repository.support.CassandraRepositoryFactoryBean; +import org.springframework.data.repository.query.QueryLookupStrategy; +import org.springframework.data.repository.query.QueryLookupStrategy.Key; + +/** + * Annotation to enable Cassandra repositories. + * + * @author Alex Shvid + * + */ + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@Import(CassandraRepositoriesRegistrar.class) +public @interface EnableCassandraRepositories { + + /** + * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.: + * {@code @EnableCassandraRepositories("org.my.pkg")} instead of + * {@code @EnableCassandraRepositories(basePackages="org.my.pkg")}. + */ + String[] value() default {}; + + /** + * Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this + * attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names. + */ + String[] basePackages() default {}; + + /** + * Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The + * package of each class specified will be scanned. Consider creating a special no-op marker class or interface in + * each package that serves no purpose other than being referenced by this attribute. + */ + Class[] basePackageClasses() default {}; + + /** + * Specifies which types are eligible for component scanning. Further narrows the set of candidate components from + * everything in {@link #basePackages()} to everything in the base packages that matches the given filter or filters. + */ + Filter[] includeFilters() default {}; + + /** + * Specifies which types are not eligible for component scanning. + */ + Filter[] excludeFilters() default {}; + + /** + * Returns the postfix to be used when looking up custom repository implementations. Defaults to {@literal Impl}. So + * for a repository named {@code UserRepository} the corresponding implementation class will be looked up scanning for + * {@code UserRepositoryImpl}. + * + * @return + */ + String repositoryImplementationPostfix() default "Impl"; + + /** + * Configures the location of where to find the Spring Data named queries properties file. Will default to + * {@code META-INFO/casasndra-named-queries.properties}. + * + * @return + */ + String namedQueriesLocation() default ""; + + /** + * Returns the key of the {@link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to + * {@link Key#CREATE_IF_NOT_FOUND}. + * + * @return + */ + Key queryLookupStrategy() default Key.CREATE_IF_NOT_FOUND; + + /** + * Returns the {@link FactoryBean} class to be used for each repository instance. Defaults to + * {@link CassandraRepositoryFactoryBean}. + * + * @return + */ + Class repositoryFactoryBeanClass() default CassandraRepositoryFactoryBean.class; + + /** + * Configures the name of the {@link CassandraDataTemplate} bean to be used with the repositories detected. + * + * @return + */ + String cassandraDataTemplateRef() default "cassandraDataTemplate"; + + /** + * Whether to automatically create indexes for query methods defined in the repository interface. + * + * @return + */ + boolean createIndexesForQueryMethods() default false; + +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/CassandraEntityInformation.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/CassandraEntityInformation.java new file mode 100644 index 000000000..528defa6d --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/CassandraEntityInformation.java @@ -0,0 +1,44 @@ +/* + * Copyright 2011 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.repository.query; + +import java.io.Serializable; + +import org.springframework.data.repository.core.EntityInformation; + +/** + * Cassandra specific {@link EntityInformation}. + * + * @author Alex Shvid + * + */ +public interface CassandraEntityInformation extends EntityInformation { + + /** + * Returns the name of the table the entity shall be persisted to. + * + * @return + */ + String getTableName(); + + /** + * Returns the column that the id will be persisted to. + * + * @return + */ + String getIdColumn(); + +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/CassandraEntityMetadata.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/CassandraEntityMetadata.java new file mode 100644 index 000000000..d0f49c238 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/CassandraEntityMetadata.java @@ -0,0 +1,35 @@ +/* + * Copyright 2011 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.repository.query; + +import org.springframework.data.repository.core.EntityMetadata; + +/** + * Extension of {@link EntityMetadata} to additionally expose the table name an entity shall be persisted to. + * + * @author Alex Shvid + * + * @param + */ +public interface CassandraEntityMetadata extends EntityMetadata { + + /** + * Returns the name of the table the entity shall be persisted to. + * + * @return + */ + String getTableName(); +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactory.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactory.java new file mode 100644 index 000000000..e59caa323 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactory.java @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2012 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.repository.support; + +import java.io.Serializable; + +import org.springframework.data.cassandra.core.CassandraDataTemplate; +import org.springframework.data.cassandra.mapping.CassandraPersistentEntity; +import org.springframework.data.cassandra.mapping.CassandraPersistentProperty; +import org.springframework.data.cassandra.repository.CassandraRepository; +import org.springframework.data.cassandra.repository.query.CassandraEntityInformation; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mapping.model.MappingException; +import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.core.support.RepositoryFactorySupport; +import org.springframework.util.Assert; + +/** + * Factory to create {@link CassandraRepository} instances. + * + * @author Alex Shvid + * + */ + +public class CassandraRepositoryFactory extends RepositoryFactorySupport { + + private final CassandraDataTemplate cassandraDataTemplate; + private final MappingContext, CassandraPersistentProperty> mappingContext; + + /** + * Creates a new {@link MongoRepositoryFactory} with the given {@link MongoOperations}. + * + * @param mongoOperations must not be {@literal null} + */ + public CassandraRepositoryFactory(CassandraDataTemplate cassandraDataTemplate) { + + Assert.notNull(cassandraDataTemplate); + + this.cassandraDataTemplate = cassandraDataTemplate; + this.mappingContext = cassandraDataTemplate.getConverter().getMappingContext(); + } + + @Override + protected Class getRepositoryBaseClass(RepositoryMetadata metadata) { + return SimpleCassandraRepository.class; + } + + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected Object getTargetRepository(RepositoryMetadata metadata) { + + CassandraEntityInformation entityInformation = getEntityInformation(metadata.getDomainType()); + + return new SimpleCassandraRepository(entityInformation, cassandraDataTemplate); + + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getEntityInformation(java.lang.Class) + */ + @Override + @SuppressWarnings("unchecked") + public CassandraEntityInformation getEntityInformation(Class domainClass) { + + CassandraPersistentEntity entity = mappingContext.getPersistentEntity(domainClass); + + if (entity == null) { + throw new MappingException(String.format("Could not lookup mapping metadata for domain class %s!", + domainClass.getName())); + } + + return new MappingCassandraEntityInformation((CassandraPersistentEntity) entity); + } +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactoryBean.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactoryBean.java new file mode 100644 index 000000000..ce3af5980 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactoryBean.java @@ -0,0 +1,66 @@ +/* + * Copyright 2011 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.repository.support; + +import java.io.Serializable; + +import org.springframework.data.cassandra.core.CassandraDataTemplate; +import org.springframework.data.cassandra.repository.CassandraRepository; +import org.springframework.data.repository.Repository; +import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport; +import org.springframework.data.repository.core.support.RepositoryFactorySupport; +import org.springframework.util.Assert; + +/** + * {@link org.springframework.beans.factory.FactoryBean} to create {@link CassandraRepository} instances. + * + * @author Alex Shvid + * + */ +public class CassandraRepositoryFactoryBean, S, ID extends Serializable> extends + RepositoryFactoryBeanSupport { + + private CassandraDataTemplate cassandraDataTemplate; + + @Override + protected RepositoryFactorySupport createRepositoryFactory() { + return new CassandraRepositoryFactory(cassandraDataTemplate); + } + + /** + * Configures the {@link CassandraDataTemplate} to be used. + * + * @param operations the operations to set + */ + public void setCassandraDataTemplate(CassandraDataTemplate cassandraDataTemplate) { + this.cassandraDataTemplate = cassandraDataTemplate; + setMappingContext(cassandraDataTemplate.getConverter().getMappingContext()); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.support.RepositoryFactoryBeanSupport + * #afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() { + super.afterPropertiesSet(); + Assert.notNull(cassandraDataTemplate, "cassandraDataTemplate must not be null!"); + } + +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/MappingCassandraEntityInformation.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/MappingCassandraEntityInformation.java new file mode 100644 index 000000000..a49c61178 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/MappingCassandraEntityInformation.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011 by the original author(s). + * + * 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.repository.support; + +import java.io.Serializable; + +import org.springframework.data.cassandra.mapping.CassandraPersistentEntity; +import org.springframework.data.cassandra.mapping.CassandraPersistentProperty; +import org.springframework.data.cassandra.repository.query.CassandraEntityInformation; +import org.springframework.data.mapping.model.BeanWrapper; +import org.springframework.data.repository.core.support.AbstractEntityInformation; + +/** + * {@link CassandraEntityInformation} implementation using a {@link CassandraPersistentEntity} instance to lookup the + * necessary information. Can be configured with a custom collection to be returned which will trump the one returned by + * the {@link CassandraPersistentEntity} if given. + * + * @author Alex Shvid + * + */ +public class MappingCassandraEntityInformation extends AbstractEntityInformation + implements CassandraEntityInformation { + + private final CassandraPersistentEntity entityMetadata; + private final String customTableName; + + /** + * Creates a new {@link MappingCassandraEntityInformation} for the given {@link CassandraPersistentEntity}. + * + * @param entity must not be {@literal null}. + */ + public MappingCassandraEntityInformation(CassandraPersistentEntity entity) { + this(entity, null); + } + + /** + * Creates a new {@link MappingCassandraEntityInformation} for the given {@link CassandraPersistentEntity} and custom + * table name. + * + * @param entity must not be {@literal null}. + * @param customTableName + */ + public MappingCassandraEntityInformation(CassandraPersistentEntity entity, String customTableName) { + super(entity.getType()); + this.entityMetadata = entity; + this.customTableName = customTableName; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.support.EntityInformation#getId(java.lang.Object) + */ + @SuppressWarnings("unchecked") + @Override + public ID getId(T entity) { + + CassandraPersistentProperty idProperty = entityMetadata.getIdProperty(); + + if (idProperty == null) { + return null; + } + + try { + return (ID) BeanWrapper.create(entity, null).getProperty(idProperty); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /* (non-Javadoc) + * @see org.springframework.data.repository.support.EntityInformation#getIdType() + */ + @SuppressWarnings("unchecked") + @Override + public Class getIdType() { + return (Class) entityMetadata.getIdProperty().getType(); + } + + /* (non-Javadoc) + * @see org.springframework.data.mongodb.repository.CassandraEntityInformation#getTableName() + */ + @Override + public String getTableName() { + return customTableName == null ? entityMetadata.getTable() : customTableName; + } + + /* (non-Javadoc) + * @see org.springframework.data.mongodb.repository.CassandraEntityInformation#getIdColumn() + */ + public String getIdColumn() { + return entityMetadata.getIdProperty().getName(); + } + +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/SimpleCassandraRepository.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/SimpleCassandraRepository.java new file mode 100644 index 000000000..385a768ed --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/SimpleCassandraRepository.java @@ -0,0 +1,237 @@ +/* + * Copyright 2010-2012 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.repository.support; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.springframework.cassandra.core.CassandraOperations; +import org.springframework.data.cassandra.core.CassandraDataOperations; +import org.springframework.data.cassandra.core.CassandraDataTemplate; +import org.springframework.data.cassandra.repository.CassandraRepository; +import org.springframework.data.cassandra.repository.query.CassandraEntityInformation; +import org.springframework.util.Assert; + +import com.datastax.driver.core.querybuilder.Clause; +import com.datastax.driver.core.querybuilder.Delete; +import com.datastax.driver.core.querybuilder.QueryBuilder; +import com.datastax.driver.core.querybuilder.Select; + +/** + * Repository base implementation for Cassandra. + * + * @author Alex Shvid + * + */ + +public class SimpleCassandraRepository implements CassandraRepository { + + private final CassandraDataTemplate cassandraDataTemplate; + private final CassandraEntityInformation entityInformation; + + /** + * Creates a new {@link SimpleCassandraRepository} for the given {@link CassandraEntityInformation} and + * {@link CassandraDataTemplate}. + * + * @param metadata must not be {@literal null}. + * @param template must not be {@literal null}. + */ + public SimpleCassandraRepository(CassandraEntityInformation metadata, + CassandraDataTemplate cassandraDataTemplate) { + + Assert.notNull(cassandraDataTemplate); + Assert.notNull(metadata); + + this.entityInformation = metadata; + this.cassandraDataTemplate = cassandraDataTemplate; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#save(java.lang.Object) + */ + public S save(S entity) { + + Assert.notNull(entity, "Entity must not be null!"); + cassandraDataTemplate.insert(entity, entityInformation.getTableName()); + return entity; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable) + */ + public List save(Iterable entities) { + + Assert.notNull(entities, "The given Iterable of entities not be null!"); + + List result = new ArrayList(); + + for (S entity : entities) { + save(entity); + result.add(entity); + } + + return result; + } + + private Clause getIdClause(ID id) { + Clause clause = QueryBuilder.eq(entityInformation.getIdColumn(), id); + return clause; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#findOne(java.io.Serializable) + */ + public T findOne(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.selectOne(select, entityInformation.getJavaType()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#exists(java.io.Serializable) + */ + public boolean exists(ID id) { + + Assert.notNull(id, "The given id must not be null!"); + + Select select = QueryBuilder.select().countAll().from(entityInformation.getTableName()); + select.where(getIdClause(id)); + + Long num = cassandraDataTemplate.count(select); + return num != null && num.longValue() > 0; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#count() + */ + public long count() { + return cassandraDataTemplate.count(entityInformation.getTableName()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#delete(java.io.Serializable) + */ + public void delete(ID id) { + Assert.notNull(id, "The given id must not be null!"); + + Delete delete = QueryBuilder.delete().all().from(entityInformation.getTableName()); + delete.where(getIdClause(id)); + + cassandraDataTemplate.execute(delete.getQueryString()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#delete(java.lang.Object) + */ + public void delete(T entity) { + Assert.notNull(entity, "The given entity must not be null!"); + delete(entityInformation.getId(entity)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#delete(java.lang.Iterable) + */ + public void delete(Iterable entities) { + + Assert.notNull(entities, "The given Iterable of entities not be null!"); + + for (T entity : entities) { + delete(entity); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#deleteAll() + */ + public void deleteAll() { + cassandraDataTemplate.truncate(entityInformation.getTableName()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#findAll() + */ + public List findAll() { + Select select = QueryBuilder.select().all().from(entityInformation.getTableName()); + return findAll(select); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#findAll(java.lang.Iterable) + */ + public Iterable findAll(Iterable ids) { + + List parameters = new ArrayList(); + for (ID id : ids) { + parameters.add(id); + } + Clause clause = QueryBuilder.in(entityInformation.getIdColumn(), parameters.toArray()); + Select select = QueryBuilder.select().all().from(entityInformation.getTableName()); + select.where(clause); + + return findAll(select); + } + + private List findAll(Select query) { + + if (query == null) { + return Collections.emptyList(); + } + + return cassandraDataTemplate.select(query, entityInformation.getJavaType()); + } + + /** + * Returns the underlying {@link CassandraOperations} instance. + * + * @return + */ + protected CassandraOperations getCassandraOperations() { + return this.cassandraDataTemplate; + } + + /** + * Returns the underlying {@link CassandraDataOperations} instance. + * + * @return + */ + protected CassandraDataOperations getCassandraDataOperations() { + return this.cassandraDataTemplate; + } + + /** + * @return the entityInformation + */ + protected CassandraEntityInformation getEntityInformation() { + return entityInformation; + } + +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepository.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepository.java new file mode 100644 index 000000000..99256f7f3 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepository.java @@ -0,0 +1,29 @@ +/* + * Copyright 2011 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.repository; + +import org.springframework.data.cassandra.repository.CassandraRepository; +import org.springframework.data.cassandra.test.integration.table.User; + +/** + * Sample repository managing {@link User} entities. + * + * @author Alex Shvid + * + */ +public interface UserRepository extends CassandraRepository { + +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests.java new file mode 100644 index 000000000..fc33c7a07 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests.java @@ -0,0 +1,168 @@ +/* + * Copyright 2011-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.repository; + +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.apache.cassandra.exceptions.ConfigurationException; +import org.apache.thrift.transport.TTransportException; +import org.cassandraunit.utils.EmbeddedCassandraServerHelper; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.cassandra.core.CassandraDataOperations; +import org.springframework.data.cassandra.test.integration.table.User; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.google.common.collect.Lists; + +/** + * Base class for tests for {@link UserRepository}. + * + * @author Alex Shvid + * + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class UserRepositoryIntegrationTests { + + @Autowired + protected UserRepository repository; + + @Autowired + protected CassandraDataOperations dataOperations; + + User tom, bob, alice, scott; + + List all; + + @BeforeClass + public static void startCassandra() throws IOException, TTransportException, ConfigurationException, + InterruptedException { + EmbeddedCassandraServerHelper.startEmbeddedCassandra("cassandra.yaml"); + } + + @Before + public void setUp() throws InterruptedException { + + repository.deleteAll(); + + tom = new User(); + tom.setUsername("tom"); + tom.setFirstName("Tom"); + tom.setLastName("Ron"); + tom.setPassword("123"); + tom.setPlace("SF"); + + bob = new User(); + bob.setUsername("bob"); + bob.setFirstName("Bob"); + bob.setLastName("White"); + bob.setPassword("555"); + bob.setPlace("NY"); + + alice = new User(); + alice.setUsername("alice"); + alice.setFirstName("Alice"); + alice.setLastName("Red"); + alice.setPassword("777"); + alice.setPlace("LA"); + + scott = new User(); + scott.setUsername("scott"); + scott.setFirstName("Scott"); + scott.setLastName("Van"); + scott.setPassword("444"); + scott.setPlace("Boston"); + + all = dataOperations.insert(Arrays.asList(tom, bob, alice, scott)); + } + + @Test + public void findsUserById() throws Exception { + + User user = repository.findOne(bob.getUsername()); + Assert.assertNotNull(user); + assertEquals(bob, user); + + } + + @Test + public void findsAll() throws Exception { + List result = Lists.newArrayList(repository.findAll()); + assertThat(result.size(), is(all.size())); + assertThat(result.containsAll(all), is(true)); + + } + + @Test + public void findsAllWithGivenIds() { + + Iterable result = repository.findAll(Arrays.asList(bob.getUsername(), tom.getUsername())); + assertThat(result, hasItems(bob, tom)); + assertThat(result, not(hasItems(alice, scott))); + } + + @Test + public void deletesUserCorrectly() throws Exception { + + repository.delete(tom); + + List result = Lists.newArrayList(repository.findAll()); + + assertThat(result.size(), is(all.size() - 1)); + assertThat(result, not(hasItem(tom))); + } + + @Test + public void deletesUserByIdCorrectly() { + + repository.delete(tom.getUsername().toString()); + + List result = Lists.newArrayList(repository.findAll()); + + assertThat(result.size(), is(all.size() - 1)); + assertThat(result, not(hasItem(tom))); + } + + @AfterClass + public static void stopCassandra() { + EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); + EmbeddedCassandraServerHelper.stopEmbeddedCassandra(); + } + + private static void assertEquals(User user1, User user2) { + Assert.assertEquals(user1.getUsername(), user2.getUsername()); + Assert.assertEquals(user1.getFirstName(), user2.getFirstName()); + Assert.assertEquals(user1.getLastName(), user2.getLastName()); + Assert.assertEquals(user1.getPlace(), user2.getPlace()); + Assert.assertEquals(user1.getPassword(), user2.getPassword()); + } + +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/table/User.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/table/User.java index 91349c4ac..2586d0273 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/table/User.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/table/User.java @@ -22,7 +22,7 @@ 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 + * This is an example of the Users status 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 @@ -63,9 +63,9 @@ public class User { private String password; /* - * Age + * Birth Year */ - private int age; + private int birthYear; /* * Following other users in userline @@ -142,17 +142,42 @@ public class User { } /** - * @return Returns the age. + * @return Returns the birthYear. */ - public int getAge() { - return age; + public int getBirthYear() { + return birthYear; } /** - * @param age The age to set. + * @param birthYear The birthYear to set. */ - public void setAge(int age) { - this.age = age; + public void setBirthYear(int birthYear) { + this.birthYear = birthYear; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((username == null) ? 0 : username.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + User other = (User) obj; + if (username == null) { + if (other.username != null) + return false; + } else if (!username.equals(other.username)) + return false; + return true; } } diff --git a/spring-data-cassandra/src/test/resources/META-INF/beans.xml b/spring-data-cassandra/src/test/resources/META-INF/beans.xml new file mode 100644 index 000000000..73ae3a251 --- /dev/null +++ b/spring-data-cassandra/src/test/resources/META-INF/beans.xml @@ -0,0 +1,6 @@ + + + + diff --git a/spring-data-cassandra/src/test/resources/META-INF/cassandra-named-queries.properties b/spring-data-cassandra/src/test/resources/META-INF/cassandra-named-queries.properties new file mode 100644 index 000000000..f8e240021 --- /dev/null +++ b/spring-data-cassandra/src/test/resources/META-INF/cassandra-named-queries.properties @@ -0,0 +1 @@ +User.findByNamedQuery=SELECT firstName FROM table WHERE firstName=?0 diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests-context.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests-context.xml new file mode 100644 index 000000000..27a117f07 --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests-context.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/cassandra.properties b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/cassandra.properties new file mode 100644 index 000000000..6a0dd3197 --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/cassandra.properties @@ -0,0 +1,7 @@ +cassandra.contactPoints=localhost +cassandra.port=9042 +cassandra.keyspace=TestKS123 + + + +