From 36a18cedaa580f8a9dfc47aec3623d0a76a2f15a Mon Sep 17 00:00:00 2001 From: Alex Shvid Date: Tue, 26 Nov 2013 11:32:01 -0800 Subject: [PATCH 1/5] cassandra repository integration test --- .../query/CassandraEntityMetadata.java | 35 ++++++++ .../CassandraRepositoryFactoryBean.java | 28 +++++++ .../test/integration/repository/Profile.java | 67 ++++++++++++++++ .../repository/ProfileRepository.java | 28 +++++++ .../ProfileRepositoryIntegrationTests.java | 79 +++++++++++++++++++ ...fileRepositoryIntegrationTests-context.xml | 61 ++++++++++++++ .../repository/cassandra.properties | 7 ++ 7 files changed, 305 insertions(+) create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/CassandraEntityMetadata.java create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactoryBean.java create mode 100644 spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/Profile.java create mode 100644 spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepository.java create mode 100644 spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests.java create mode 100644 spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests-context.xml create mode 100644 spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/cassandra.properties 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/CassandraRepositoryFactoryBean.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactoryBean.java new file mode 100644 index 000000000..e32ba9261 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactoryBean.java @@ -0,0 +1,28 @@ +/* + * 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 org.springframework.data.cassandra.repository.CassandraRepository; + +/** + * {@link org.springframework.beans.factory.FactoryBean} to create {@link CassandraRepository} instances. + * + * @author Alex Shvid + * + */ +public class CassandraRepositoryFactoryBean { + +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/Profile.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/Profile.java new file mode 100644 index 000000000..718c923b8 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/Profile.java @@ -0,0 +1,67 @@ +/* + * 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; + +/** + * Sample domain class got from Webby social network site. + * + * @author Alex Shvid + * + */ +public class Profile { + + public enum Gender { + MALE, FEMALE; + } + + private Long profileId; + private String firstName; + private String lastName; + private Gender gender; + + public Long getProfileId() { + return profileId; + } + + public void setProfileId(Long profileId) { + this.profileId = profileId; + } + + 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 Gender getGender() { + return gender; + } + + public void setGender(Gender gender) { + this.gender = gender; + } + +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepository.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepository.java new file mode 100644 index 000000000..6fe41cc81 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepository.java @@ -0,0 +1,28 @@ +/* + * 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; + +/** + * Sample repository managing {@link Profile} entities. + * + * @author Alex Shvid + * + */ +public interface ProfileRepository extends CassandraRepository { + +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests.java new file mode 100644 index 000000000..8248216d6 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests.java @@ -0,0 +1,79 @@ +/* + * 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 java.io.IOException; + +import org.apache.cassandra.exceptions.ConfigurationException; +import org.apache.thrift.transport.TTransportException; +import org.cassandraunit.utils.EmbeddedCassandraServerHelper; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.cassandra.core.CassandraDataOperations; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Base class for tests for {@link ProfileRepository}. + * + * @author Alex Shvid + * + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class ProfileRepositoryIntegrationTests { + + // @Autowired + // protected ProfileRepository repository; + + @Autowired + CassandraDataOperations operations; + + @BeforeClass + public static void startCassandra() throws IOException, TTransportException, ConfigurationException, + InterruptedException { + EmbeddedCassandraServerHelper.startEmbeddedCassandra("cassandra.yaml"); + } + + @Before + public void setUp() throws InterruptedException { + + // repository.deleteAll(); + + } + + @Test + public void findsProfileById() throws Exception { + + System.out.println("find profile by id"); + } + + @After + public void clearCassandra() { + EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); + } + + @AfterClass + public static void stopCassandra() { + EmbeddedCassandraServerHelper.stopEmbeddedCassandra(); + } + +} diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests-context.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests-context.xml new file mode 100644 index 000000000..9a5e68f7d --- /dev/null +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests-context.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + From fe71cb6050433b65e7a62913f6164bc012b2b861 Mon Sep 17 00:00:00 2001 From: Alex Shvid Date: Tue, 26 Nov 2013 21:30:37 -0800 Subject: [PATCH 2/5] created SimpleCassandraRepository --- .../core/CassandraDataOperations.java | 28 +- .../cassandra/core/CassandraDataTemplate.java | 49 +++- .../query/CassandraEntityInformation.java | 44 ++++ .../support/CassandraRepositoryFactory.java | 92 +++++++ .../CassandraRepositoryFactoryBean.java | 51 +++- .../MappingCassandraEntityInformation.java | 107 ++++++++ .../support/SimpleCassandraRepository.java | 244 ++++++++++++++++++ .../src/test/resources/META-INF/beans.xml | 6 + .../cassandra-named-queries.properties | 1 + ...fileRepositoryIntegrationTests-context.xml | 17 +- 10 files changed, 621 insertions(+), 18 deletions(-) create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/query/CassandraEntityInformation.java create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactory.java create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/MappingCassandraEntityInformation.java create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/SimpleCassandraRepository.java create mode 100644 spring-data-cassandra/src/test/resources/META-INF/beans.xml create mode 100644 spring-data-cassandra/src/test/resources/META-INF/cassandra-named-queries.properties 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..6772c7827 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) 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/support/CassandraRepositoryFactory.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactory.java new file mode 100644 index 000000000..0fa105867 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactory.java @@ -0,0 +1,92 @@ +/* + * 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.cassandra.core.CassandraOperations; +import org.springframework.data.cassandra.core.CassandraDataOperations; +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 CassandraOperations operations; + private final CassandraDataOperations dataOperations; + private final MappingContext, CassandraPersistentProperty> mappingContext; + + /** + * Creates a new {@link MongoRepositoryFactory} with the given {@link MongoOperations}. + * + * @param mongoOperations must not be {@literal null} + */ + public CassandraRepositoryFactory(CassandraOperations operations, CassandraDataOperations dataOperations) { + + Assert.notNull(operations); + Assert.notNull(dataOperations); + + this.operations = operations; + this.dataOperations = dataOperations; + this.mappingContext = dataOperations.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, operations, dataOperations); + + } + + /* + * (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 index e32ba9261..67471d546 100644 --- 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 @@ -15,7 +15,15 @@ */ package org.springframework.data.cassandra.repository.support; +import java.io.Serializable; + +import org.springframework.cassandra.core.CassandraOperations; +import org.springframework.data.cassandra.core.CassandraDataOperations; 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. @@ -23,6 +31,47 @@ import org.springframework.data.cassandra.repository.CassandraRepository; * @author Alex Shvid * */ -public class CassandraRepositoryFactoryBean { +public class CassandraRepositoryFactoryBean, S, ID extends Serializable> extends + RepositoryFactoryBeanSupport { + + private CassandraOperations operations; + private CassandraDataOperations dataOperations; + + @Override + protected RepositoryFactorySupport createRepositoryFactory() { + return new CassandraRepositoryFactory(operations, dataOperations); + } + + /** + * Configures the {@link CassandraOperations} to be used. + * + * @param operations the operations to set + */ + public void setCassandraOperations(CassandraOperations operations) { + this.operations = operations; + } + + /** + * Configures the {@link CassandraDataOperations} to be used. + * + * @param operations the operations to set + */ + public void setCassandraDataOperations(CassandraDataOperations dataOperations) { + this.dataOperations = dataOperations; + setMappingContext(dataOperations.getConverter().getMappingContext()); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.support.RepositoryFactoryBeanSupport + * #afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() { + super.afterPropertiesSet(); + Assert.notNull(dataOperations, "CassandraDataOperations 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..cee155359 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/SimpleCassandraRepository.java @@ -0,0 +1,244 @@ +/* + * 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 CassandraOperations operations; + private final CassandraDataOperations dataOperations; + 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, CassandraOperations operations, + CassandraDataOperations dataOperations) { + + Assert.notNull(operations); + Assert.notNull(dataOperations); + Assert.notNull(metadata); + + this.entityInformation = metadata; + this.operations = operations; + this.dataOperations = dataOperations; + } + + /* + * (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!"); + + // INSERT OR OPDATE? + + dataOperations.update(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 dataOperations.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 = dataOperations.count(select); + return num != null && num.longValue() > 0; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.CrudRepository#count() + */ + public long count() { + return dataOperations.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)); + + operations.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() { + Delete delete = QueryBuilder.delete().all().from(entityInformation.getTableName()); + operations.execute(delete.getQueryString()); + } + + /* + * (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 dataOperations.select(query, entityInformation.getJavaType()); + } + + /** + * Returns the underlying {@link CassandraOperations} instance. + * + * @return + */ + protected CassandraOperations getCassandraOperations() { + return this.operations; + } + + /** + * Returns the underlying {@link CassandraDataOperations} instance. + * + * @return + */ + protected CassandraDataOperations getCassandraDataOperations() { + return this.dataOperations; + } + + /** + * @return the entityInformation + */ + protected CassandraEntityInformation getEntityInformation() { + return entityInformation; + } + +} 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..168cc6a11 --- /dev/null +++ b/spring-data-cassandra/src/test/resources/META-INF/cassandra-named-queries.properties @@ -0,0 +1 @@ +Profile.findByNamedQuery=SELECT firstName FROM table WHERE firstName=?0 diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests-context.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests-context.xml index 9a5e68f7d..711e28f53 100644 --- a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests-context.xml +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests-context.xml @@ -2,9 +2,11 @@ + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> @@ -58,4 +60,17 @@ + + + + + + + + + + + + + From fa35d320f978b7236c70d2058e3fcc49c56d7d67 Mon Sep 17 00:00:00 2001 From: Alex Shvid Date: Wed, 27 Nov 2013 11:51:16 -0800 Subject: [PATCH 3/5] SimpleCassandraRepository refactoring --- .../core/CassandraAdminTemplate.java | 2 +- .../cassandra/core/CassandraDataTemplate.java | 1 + .../support/CassandraRepositoryFactory.java | 18 ++--- .../CassandraRepositoryFactoryBean.java | 27 +++----- .../support/SimpleCassandraRepository.java | 36 +++++----- .../test/integration/repository/Profile.java | 67 ------------------- ...ileRepository.java => UserRepository.java} | 5 +- ...va => UserRepositoryIntegrationTests.java} | 26 +++++-- .../test/integration/table/User.java | 18 ++--- .../cassandra-named-queries.properties | 2 +- ...serRepositoryIntegrationTests-context.xml} | 5 +- 11 files changed, 66 insertions(+), 141 deletions(-) delete mode 100644 spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/Profile.java rename spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/{ProfileRepository.java => UserRepository.java} (80%) rename spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/{ProfileRepositoryIntegrationTests.java => UserRepositoryIntegrationTests.java} (80%) rename spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/{ProfileRepositoryIntegrationTests-context.xml => UserRepositoryIntegrationTests-context.xml} (94%) 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/CassandraDataTemplate.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraDataTemplate.java index 6772c7827..9b2c175a3 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 @@ -1204,6 +1204,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/support/CassandraRepositoryFactory.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/CassandraRepositoryFactory.java index 0fa105867..e59caa323 100644 --- 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 @@ -17,8 +17,7 @@ package org.springframework.data.cassandra.repository.support; import java.io.Serializable; -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.mapping.CassandraPersistentEntity; import org.springframework.data.cassandra.mapping.CassandraPersistentProperty; import org.springframework.data.cassandra.repository.CassandraRepository; @@ -38,8 +37,7 @@ import org.springframework.util.Assert; public class CassandraRepositoryFactory extends RepositoryFactorySupport { - private final CassandraOperations operations; - private final CassandraDataOperations dataOperations; + private final CassandraDataTemplate cassandraDataTemplate; private final MappingContext, CassandraPersistentProperty> mappingContext; /** @@ -47,14 +45,12 @@ public class CassandraRepositoryFactory extends RepositoryFactorySupport { * * @param mongoOperations must not be {@literal null} */ - public CassandraRepositoryFactory(CassandraOperations operations, CassandraDataOperations dataOperations) { + public CassandraRepositoryFactory(CassandraDataTemplate cassandraDataTemplate) { - Assert.notNull(operations); - Assert.notNull(dataOperations); + Assert.notNull(cassandraDataTemplate); - this.operations = operations; - this.dataOperations = dataOperations; - this.mappingContext = dataOperations.getConverter().getMappingContext(); + this.cassandraDataTemplate = cassandraDataTemplate; + this.mappingContext = cassandraDataTemplate.getConverter().getMappingContext(); } @Override @@ -68,7 +64,7 @@ public class CassandraRepositoryFactory extends RepositoryFactorySupport { CassandraEntityInformation entityInformation = getEntityInformation(metadata.getDomainType()); - return new SimpleCassandraRepository(entityInformation, operations, dataOperations); + return new SimpleCassandraRepository(entityInformation, cassandraDataTemplate); } 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 index 67471d546..ce3af5980 100644 --- 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 @@ -17,8 +17,7 @@ package org.springframework.data.cassandra.repository.support; import java.io.Serializable; -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.repository.Repository; import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport; @@ -34,31 +33,21 @@ import org.springframework.util.Assert; public class CassandraRepositoryFactoryBean, S, ID extends Serializable> extends RepositoryFactoryBeanSupport { - private CassandraOperations operations; - private CassandraDataOperations dataOperations; + private CassandraDataTemplate cassandraDataTemplate; @Override protected RepositoryFactorySupport createRepositoryFactory() { - return new CassandraRepositoryFactory(operations, dataOperations); + return new CassandraRepositoryFactory(cassandraDataTemplate); } /** - * Configures the {@link CassandraOperations} to be used. + * Configures the {@link CassandraDataTemplate} to be used. * * @param operations the operations to set */ - public void setCassandraOperations(CassandraOperations operations) { - this.operations = operations; - } - - /** - * Configures the {@link CassandraDataOperations} to be used. - * - * @param operations the operations to set - */ - public void setCassandraDataOperations(CassandraDataOperations dataOperations) { - this.dataOperations = dataOperations; - setMappingContext(dataOperations.getConverter().getMappingContext()); + public void setCassandraDataTemplate(CassandraDataTemplate cassandraDataTemplate) { + this.cassandraDataTemplate = cassandraDataTemplate; + setMappingContext(cassandraDataTemplate.getConverter().getMappingContext()); } /* @@ -71,7 +60,7 @@ public class CassandraRepositoryFactoryBean, S, ID e @Override public void afterPropertiesSet() { super.afterPropertiesSet(); - Assert.notNull(dataOperations, "CassandraDataOperations must not be null!"); + Assert.notNull(cassandraDataTemplate, "cassandraDataTemplate must not be null!"); } } 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 index cee155359..b7ccd8de7 100644 --- 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 @@ -31,6 +31,7 @@ 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; +import com.datastax.driver.core.querybuilder.Truncate; /** * Repository base implementation for Cassandra. @@ -41,8 +42,7 @@ import com.datastax.driver.core.querybuilder.Select; public class SimpleCassandraRepository implements CassandraRepository { - private final CassandraOperations operations; - private final CassandraDataOperations dataOperations; + private final CassandraDataTemplate cassandraDataTemplate; private final CassandraEntityInformation entityInformation; /** @@ -52,16 +52,14 @@ public class SimpleCassandraRepository implements Ca * @param metadata must not be {@literal null}. * @param template must not be {@literal null}. */ - public SimpleCassandraRepository(CassandraEntityInformation metadata, CassandraOperations operations, - CassandraDataOperations dataOperations) { + public SimpleCassandraRepository(CassandraEntityInformation metadata, + CassandraDataTemplate cassandraDataTemplate) { - Assert.notNull(operations); - Assert.notNull(dataOperations); + Assert.notNull(cassandraDataTemplate); Assert.notNull(metadata); this.entityInformation = metadata; - this.operations = operations; - this.dataOperations = dataOperations; + this.cassandraDataTemplate = cassandraDataTemplate; } /* @@ -71,10 +69,7 @@ public class SimpleCassandraRepository implements Ca public S save(S entity) { Assert.notNull(entity, "Entity must not be null!"); - - // INSERT OR OPDATE? - - dataOperations.update(entity, entityInformation.getTableName()); + cassandraDataTemplate.insert(entity, entityInformation.getTableName()); return entity; } @@ -111,7 +106,7 @@ public class SimpleCassandraRepository implements Ca Select select = QueryBuilder.select().all().from(entityInformation.getTableName()); select.where(getIdClause(id)); - return dataOperations.selectOne(select, entityInformation.getJavaType()); + return cassandraDataTemplate.selectOne(select, entityInformation.getJavaType()); } /* @@ -125,7 +120,7 @@ public class SimpleCassandraRepository implements Ca Select select = QueryBuilder.select().countAll().from(entityInformation.getTableName()); select.where(getIdClause(id)); - Long num = dataOperations.count(select); + Long num = cassandraDataTemplate.count(select); return num != null && num.longValue() > 0; } @@ -134,7 +129,7 @@ public class SimpleCassandraRepository implements Ca * @see org.springframework.data.repository.CrudRepository#count() */ public long count() { - return dataOperations.count(entityInformation.getTableName()); + return cassandraDataTemplate.count(entityInformation.getTableName()); } /* @@ -147,7 +142,7 @@ public class SimpleCassandraRepository implements Ca Delete delete = QueryBuilder.delete().all().from(entityInformation.getTableName()); delete.where(getIdClause(id)); - operations.execute(delete.getQueryString()); + cassandraDataTemplate.execute(delete.getQueryString()); } /* @@ -177,8 +172,7 @@ public class SimpleCassandraRepository implements Ca * @see org.springframework.data.repository.CrudRepository#deleteAll() */ public void deleteAll() { - Delete delete = QueryBuilder.delete().all().from(entityInformation.getTableName()); - operations.execute(delete.getQueryString()); + // cassandraDataTemplate.truncate(entityInformation.getTableName()); } /* @@ -213,7 +207,7 @@ public class SimpleCassandraRepository implements Ca return Collections.emptyList(); } - return dataOperations.select(query, entityInformation.getJavaType()); + return cassandraDataTemplate.select(query, entityInformation.getJavaType()); } /** @@ -222,7 +216,7 @@ public class SimpleCassandraRepository implements Ca * @return */ protected CassandraOperations getCassandraOperations() { - return this.operations; + return this.cassandraDataTemplate; } /** @@ -231,7 +225,7 @@ public class SimpleCassandraRepository implements Ca * @return */ protected CassandraDataOperations getCassandraDataOperations() { - return this.dataOperations; + return this.cassandraDataTemplate; } /** diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/Profile.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/Profile.java deleted file mode 100644 index 718c923b8..000000000 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/Profile.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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; - -/** - * Sample domain class got from Webby social network site. - * - * @author Alex Shvid - * - */ -public class Profile { - - public enum Gender { - MALE, FEMALE; - } - - private Long profileId; - private String firstName; - private String lastName; - private Gender gender; - - public Long getProfileId() { - return profileId; - } - - public void setProfileId(Long profileId) { - this.profileId = profileId; - } - - 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 Gender getGender() { - return gender; - } - - public void setGender(Gender gender) { - this.gender = gender; - } - -} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepository.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepository.java similarity index 80% rename from spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepository.java rename to spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepository.java index 6fe41cc81..99256f7f3 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepository.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepository.java @@ -16,13 +16,14 @@ 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 Profile} entities. + * Sample repository managing {@link User} entities. * * @author Alex Shvid * */ -public interface ProfileRepository extends CassandraRepository { +public interface UserRepository extends CassandraRepository { } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests.java similarity index 80% rename from spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests.java rename to spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests.java index 8248216d6..1569092bf 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests.java @@ -28,24 +28,27 @@ 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; /** - * Base class for tests for {@link ProfileRepository}. + * Base class for tests for {@link UserRepository}. * * @author Alex Shvid * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class ProfileRepositoryIntegrationTests { - - // @Autowired - // protected ProfileRepository repository; +public class UserRepositoryIntegrationTests { @Autowired - CassandraDataOperations operations; + protected UserRepository repository; + + @Autowired + protected CassandraDataOperations dataOperations; + + User alex; @BeforeClass public static void startCassandra() throws IOException, TTransportException, ConfigurationException, @@ -56,7 +59,16 @@ public class ProfileRepositoryIntegrationTests { @Before public void setUp() throws InterruptedException { - // repository.deleteAll(); + repository.deleteAll(); + + alex = new User(); + alex.setUsername("alex"); + alex.setFirstName("Alex"); + alex.setLastName("Shvid"); + alex.setPassword("123"); + alex.setPlace("SF"); + + dataOperations.insert(alex); } 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..fb2f9dfb9 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,17 @@ 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; } } 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 index 168cc6a11..f8e240021 100644 --- 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 @@ -1 +1 @@ -Profile.findByNamedQuery=SELECT firstName FROM table WHERE firstName=?0 +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/ProfileRepositoryIntegrationTests-context.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests-context.xml similarity index 94% rename from spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests-context.xml rename to spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests-context.xml index 711e28f53..27a117f07 100644 --- a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/ProfileRepositoryIntegrationTests-context.xml +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/repository/UserRepositoryIntegrationTests-context.xml @@ -61,9 +61,8 @@ - - - + + From 21b30a0dc1215f0229a1feb7ce55c9b8760c4123 Mon Sep 17 00:00:00 2001 From: Alex Shvid Date: Wed, 27 Nov 2013 12:32:58 -0800 Subject: [PATCH 4/5] CassandraRepository config --- .../CassandraRepositoriesRegistrar.java | 54 ++++++++ ...andraRepositoryConfigurationExtension.java | 86 ++++++++++++ .../config/EnableCassandraRepositories.java | 125 ++++++++++++++++++ .../support/SimpleCassandraRepository.java | 3 +- 4 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoriesRegistrar.java create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/CassandraRepositoryConfigurationExtension.java create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/config/EnableCassandraRepositories.java 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/support/SimpleCassandraRepository.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/SimpleCassandraRepository.java index b7ccd8de7..385a768ed 100644 --- 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 @@ -31,7 +31,6 @@ 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; -import com.datastax.driver.core.querybuilder.Truncate; /** * Repository base implementation for Cassandra. @@ -172,7 +171,7 @@ public class SimpleCassandraRepository implements Ca * @see org.springframework.data.repository.CrudRepository#deleteAll() */ public void deleteAll() { - // cassandraDataTemplate.truncate(entityInformation.getTableName()); + cassandraDataTemplate.truncate(entityInformation.getTableName()); } /* From d5b57d759d3ea21dd0674c345e6eeec792faca9d Mon Sep 17 00:00:00 2001 From: Alex Shvid Date: Wed, 27 Nov 2013 14:04:33 -0800 Subject: [PATCH 5/5] SimpleCassandraRepository integration tests for User --- pom.xml | 1 + .../cassandra/core/CassandraDataTemplate.java | 2 + .../UserRepositoryIntegrationTests.java | 105 +++++++++++++++--- .../test/integration/table/User.java | 25 +++++ 4 files changed, 119 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 36bb9b097..335689a37 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/CassandraDataTemplate.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraDataTemplate.java index 9b2c175a3..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 @@ -989,6 +989,8 @@ public class CassandraDataTemplate extends CassandraTemplate implements Cassandr */ private T doSelectOne(final String query, ReadRowCallback readRowCallback) { + logger.info(query); + /* * Run the Query */ 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 index 1569092bf..fc33c7a07 100644 --- 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 @@ -15,13 +15,21 @@ */ 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.After; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -32,6 +40,8 @@ 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}. * @@ -48,7 +58,9 @@ public class UserRepositoryIntegrationTests { @Autowired protected CassandraDataOperations dataOperations; - User alex; + User tom, bob, alice, scott; + + List all; @BeforeClass public static void startCassandra() throws IOException, TTransportException, ConfigurationException, @@ -61,31 +73,96 @@ public class UserRepositoryIntegrationTests { repository.deleteAll(); - alex = new User(); - alex.setUsername("alex"); - alex.setFirstName("Alex"); - alex.setLastName("Shvid"); - alex.setPassword("123"); - alex.setPlace("SF"); + tom = new User(); + tom.setUsername("tom"); + tom.setFirstName("Tom"); + tom.setLastName("Ron"); + tom.setPassword("123"); + tom.setPlace("SF"); - dataOperations.insert(alex); + 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 findsProfileById() throws Exception { + public void findsAll() throws Exception { + List result = Lists.newArrayList(repository.findAll()); + assertThat(result.size(), is(all.size())); + assertThat(result.containsAll(all), is(true)); - System.out.println("find profile by id"); } - @After - public void clearCassandra() { - EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); + @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 fb2f9dfb9..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 @@ -155,4 +155,29 @@ public class User { 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; + } + }