diff --git a/src/main/java/org/springframework/data/couchbase/repository/query/CouchbaseEntityInformation.java b/src/main/java/org/springframework/data/couchbase/repository/query/CouchbaseEntityInformation.java index 33ee8f1a..fc6b1821 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/query/CouchbaseEntityInformation.java +++ b/src/main/java/org/springframework/data/couchbase/repository/query/CouchbaseEntityInformation.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013, 2014 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. @@ -17,6 +17,7 @@ package org.springframework.data.couchbase.repository.query; import org.springframework.data.repository.core.EntityInformation; +import org.springframework.data.repository.core.support.RepositoryFactorySupport; import java.io.Serializable; @@ -26,4 +27,5 @@ import java.io.Serializable; * @author Michael Nitschinger */ public interface CouchbaseEntityInformation extends EntityInformation { + } diff --git a/src/main/java/org/springframework/data/couchbase/repository/query/CouchbaseQueryMethod.java b/src/main/java/org/springframework/data/couchbase/repository/query/CouchbaseQueryMethod.java new file mode 100644 index 00000000..5442c663 --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/repository/query/CouchbaseQueryMethod.java @@ -0,0 +1,66 @@ +/* + * Copyright 2013, 2014 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.couchbase.repository.query; + +import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity; +import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty; +import org.springframework.data.couchbase.core.view.View; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.query.QueryMethod; + +import java.lang.reflect.Method; + +/** + * Represents a query method with couchbase extensions. + * + * @author Michael Nitschinger + */ +public class CouchbaseQueryMethod extends QueryMethod { + + private final Method method; + private final MappingContext, CouchbasePersistentProperty> mappingContext; + + public CouchbaseQueryMethod(Method method, RepositoryMetadata metadata, + MappingContext, CouchbasePersistentProperty> mappingContext) { + super(method, metadata); + + this.method = method; + this.mappingContext = mappingContext; + } + + /** + * If the method has a @View annotation. + * + * @return true if it has the annotation, false otherwise. + */ + public boolean hasViewAnnotation() { + return getViewAnnotation() != null; + } + + /** + * Returns the @View annoation if set, null otherwise. + * + * @return the view annotation of present. + */ + public View getViewAnnotation() { + return method.getAnnotation(View.class); + } + + + +} diff --git a/src/main/java/org/springframework/data/couchbase/repository/query/ViewBasedCouchbaseQuery.java b/src/main/java/org/springframework/data/couchbase/repository/query/ViewBasedCouchbaseQuery.java new file mode 100644 index 00000000..94674b86 --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/repository/query/ViewBasedCouchbaseQuery.java @@ -0,0 +1,89 @@ +/* + * Copyright 2013, 2014 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.couchbase.repository.query; + +import com.couchbase.client.protocol.views.Query; +import org.springframework.data.couchbase.core.CouchbaseOperations; +import org.springframework.data.repository.query.QueryMethod; +import org.springframework.data.repository.query.RepositoryQuery; + +/** + * Execute a repository query through the View mechanism. + * + * @author Michael Nitschinger + */ +public class ViewBasedCouchbaseQuery implements RepositoryQuery { + + private final CouchbaseQueryMethod method; + private final CouchbaseOperations operations; + + public ViewBasedCouchbaseQuery(CouchbaseQueryMethod method, CouchbaseOperations operations) { + this.method = method; + this.operations = operations; + } + + @Override + public Object execute(Object[] runtimeParams) { + Query query = null; + for (Object param : runtimeParams) { + if (param instanceof Query) { + query = (Query) param; + } else { + throw new IllegalStateException("Unknown query param: " + param); + } + } + + if (query == null) { + query = new Query(); + } + query.setReduce(false); + + return operations.findByView(designDocName(), viewName(), query, method.getEntityInformation().getJavaType()); + } + + @Override + public QueryMethod getQueryMethod() { + return method; + } + + /** + * Returns the best-guess design document name. + * + * @return the design document name. + */ + private String designDocName() { + if (method.hasViewAnnotation()) { + return method.getViewAnnotation().designDocument(); + } else { + return method.getEntityInformation().getJavaType().getSimpleName().toLowerCase(); + } + } + + /** + * Returns the best-guess view name. + * + * @return the view name. + */ + private String viewName() { + if (method.hasViewAnnotation()) { + return method.getViewAnnotation().viewName(); + } else { + return method.getName(); + } + } + +} diff --git a/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactory.java b/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactory.java index 24f5a357..f7c87c26 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactory.java +++ b/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactory.java @@ -19,14 +19,21 @@ package org.springframework.data.couchbase.repository.support; import org.springframework.data.couchbase.core.CouchbaseOperations; import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity; import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty; +import org.springframework.data.couchbase.core.view.View; import org.springframework.data.couchbase.repository.query.CouchbaseEntityInformation; +import org.springframework.data.couchbase.repository.query.CouchbaseQueryMethod; +import org.springframework.data.couchbase.repository.query.ViewBasedCouchbaseQuery; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.MappingException; +import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.support.RepositoryFactorySupport; +import org.springframework.data.repository.query.QueryLookupStrategy; +import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.util.Assert; import java.io.Serializable; +import java.lang.reflect.Method; /** * Factory to create {@link SimpleCouchbaseRepository} instances. @@ -112,4 +119,20 @@ public class CouchbaseRepositoryFactory extends RepositoryFactorySupport { return SimpleCouchbaseRepository.class; } + @Override + protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key) { + return new CouchbaseQueryLookupStrategy(); + } + + /** + * Currently, only views are supported. N1QL support to be added. + */ + private class CouchbaseQueryLookupStrategy implements QueryLookupStrategy { + @Override + public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) { + CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method, metadata, mappingContext); + return new ViewBasedCouchbaseQuery(queryMethod, couchbaseOperations); + } + } + } diff --git a/src/test/java/org/springframework/data/couchbase/repository/SimpleCouchbaseRepositoryTests.java b/src/test/java/org/springframework/data/couchbase/repository/SimpleCouchbaseRepositoryTests.java index cc7d75d5..00033329 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/SimpleCouchbaseRepositoryTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/SimpleCouchbaseRepositoryTests.java @@ -23,6 +23,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.couchbase.TestApplicationConfig; import org.springframework.data.couchbase.core.CouchbaseTemplate; import org.springframework.data.couchbase.repository.support.CouchbaseRepositoryFactory; @@ -98,4 +99,16 @@ public class SimpleCouchbaseRepositoryTests { assertEquals(100, repository.count()); } + @Test + public void shouldFindCustom() { + Iterable users = repository.customViewQuery(new Query().setLimit(2).setStale(Stale.FALSE)); + int size = 0; + for (User u : users) { + size++; + assertNotNull(u.getKey()); + assertNotNull(u.getUsername()); + } + assertEquals(2, size); + } + } diff --git a/src/test/java/org/springframework/data/couchbase/repository/UserRepository.java b/src/test/java/org/springframework/data/couchbase/repository/UserRepository.java index da78c6f7..d8c04262 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/UserRepository.java +++ b/src/test/java/org/springframework/data/couchbase/repository/UserRepository.java @@ -16,9 +16,15 @@ package org.springframework.data.couchbase.repository; +import com.couchbase.client.protocol.views.Query; +import org.springframework.data.couchbase.core.view.View; + /** * @author Michael Nitschinger */ public interface UserRepository extends CouchbaseRepository { + @View(designDocument = "user", viewName = "all") + Iterable customViewQuery(Query query); + }