DATACOUCH-64 - Enable dynamic queries on repositories.

This changeset adds dynamic queries that can be annotated with @View and also provide a custom
Query param to change properties at runtime if needed.
This commit is contained in:
Michael Nitschinger
2014-01-23 14:03:49 +01:00
parent 03ed0b5fef
commit 9452c40eeb
6 changed files with 200 additions and 1 deletions

View File

@@ -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<T, ID extends Serializable> extends EntityInformation<T, ID> {
}

View File

@@ -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<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext;
public CouchbaseQueryMethod(Method method, RepositoryMetadata metadata,
MappingContext<? extends CouchbasePersistentEntity<?>, 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);
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}
}