DATACOUCH-148 - Allow to configure repository queries consistency globally.
The consistency to apply on generated view queries (Stale) and N1QL queries (ScanConsistency) can now be chosen via the configuration, through a more abstract Consistency enumeration. It is accessed from the CouchbaseOperations interface but is used in the repository only. In xml, the consistency attribute is on the couchbase:template element (string value of the enum to be passed in). Documentation has been amended to describe this feature.
This commit is contained in:
@@ -27,6 +27,8 @@ import com.couchbase.client.java.CouchbaseCluster;
|
||||
import com.couchbase.client.java.cluster.ClusterInfo;
|
||||
import com.couchbase.client.java.env.CouchbaseEnvironment;
|
||||
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
|
||||
import com.couchbase.client.java.query.Query;
|
||||
import com.couchbase.client.java.view.ViewQuery;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -41,6 +43,7 @@ import org.springframework.data.couchbase.core.convert.translation.JacksonTransl
|
||||
import org.springframework.data.couchbase.core.convert.translation.TranslationService;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext;
|
||||
import org.springframework.data.couchbase.core.mapping.Document;
|
||||
import org.springframework.data.couchbase.core.view.Consistency;
|
||||
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
@@ -136,11 +139,16 @@ public abstract class AbstractCouchbaseConfiguration {
|
||||
/**
|
||||
* Creates a {@link CouchbaseTemplate}.
|
||||
*
|
||||
* This uses {@link #couchbaseClusterInfo()}, {@link #couchbaseClient()}, {@link #mappingCouchbaseConverter()},
|
||||
* , {@link #translationService()} and {@link #getDefaultConsistency()} for construction.
|
||||
*
|
||||
* @throws Exception on Bean construction failure.
|
||||
*/
|
||||
@Bean(name = BeanNames.COUCHBASE_TEMPLATE)
|
||||
public CouchbaseTemplate couchbaseTemplate() throws Exception {
|
||||
return new CouchbaseTemplate(couchbaseClusterInfo(), couchbaseClient(), mappingCouchbaseConverter(), translationService());
|
||||
CouchbaseTemplate template = new CouchbaseTemplate(couchbaseClusterInfo(), couchbaseClient(), mappingCouchbaseConverter(), translationService());
|
||||
template.setDefaultConsistency(getDefaultConsistency());
|
||||
return template;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,4 +265,14 @@ public abstract class AbstractCouchbaseConfiguration {
|
||||
protected FieldNamingStrategy fieldNamingStrategy() {
|
||||
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy() : PropertyNameFieldNamingStrategy.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the default consistency for generated {@link ViewQuery view queries}
|
||||
* and {@link Query N1QL queries} in repositories.
|
||||
*
|
||||
* @return the {@link Consistency consistency} to apply by default on generated queries.
|
||||
*/
|
||||
protected Consistency getDefaultConsistency() {
|
||||
return Consistency.DEFAULT_CONSISTENCY;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
@@ -23,6 +25,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.couchbase.core.CouchbaseTemplate;
|
||||
import org.springframework.data.couchbase.core.view.Consistency;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -34,6 +37,8 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class CouchbaseTemplateParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CouchbaseTemplateParser.class);
|
||||
|
||||
/**
|
||||
* Resolve the bean ID and assign a default if not set.
|
||||
*
|
||||
@@ -82,6 +87,17 @@ public class CouchbaseTemplateParser extends AbstractSingleBeanDefinitionParser
|
||||
if (StringUtils.hasText(translationServiceRef)) {
|
||||
bean.addConstructorArgReference(translationServiceRef);
|
||||
}
|
||||
|
||||
String consistencyValue = element.getAttribute("consistency");
|
||||
if (consistencyValue != null) {
|
||||
try {
|
||||
Consistency consistency = Consistency.valueOf(consistencyValue);
|
||||
bean.addPropertyValue("defaultConsistency", consistency);
|
||||
} catch (IllegalArgumentException e) {
|
||||
//bad consistency, leave default and log
|
||||
LOGGER.warn("Parsed bad consistency value " + consistencyValue + " in xml template configuration, using default");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.couchbase.client.java.view.ViewResult;
|
||||
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.data.couchbase.core.convert.translation.TranslationService;
|
||||
import org.springframework.data.couchbase.core.view.Consistency;
|
||||
|
||||
/**
|
||||
* Defines common operations on the Couchbase data source, most commonly implemented by {@link CouchbaseTemplate}.
|
||||
@@ -341,4 +342,12 @@ public interface CouchbaseOperations {
|
||||
*/
|
||||
CouchbaseConverter getConverter();
|
||||
|
||||
/**
|
||||
* Returns the {@link Consistency consistency} parameter to be used by default for generated queries (views and N1QL)
|
||||
* in repositories. Defaults to {@link Consistency#DEFAULT_CONSISTENCY}.
|
||||
*
|
||||
* @return the consistency to use for generated repository queries.
|
||||
*/
|
||||
Consistency getDefaultConsistency();
|
||||
|
||||
}
|
||||
|
||||
@@ -36,8 +36,10 @@ import com.couchbase.client.java.document.json.JsonObject;
|
||||
import com.couchbase.client.java.error.CASMismatchException;
|
||||
import com.couchbase.client.java.error.TranscodingException;
|
||||
import com.couchbase.client.java.query.Query;
|
||||
import com.couchbase.client.java.query.QueryParams;
|
||||
import com.couchbase.client.java.query.QueryResult;
|
||||
import com.couchbase.client.java.query.QueryRow;
|
||||
import com.couchbase.client.java.query.consistency.ScanConsistency;
|
||||
import com.couchbase.client.java.util.features.CouchbaseFeature;
|
||||
import com.couchbase.client.java.view.ViewQuery;
|
||||
import com.couchbase.client.java.view.ViewResult;
|
||||
@@ -65,6 +67,7 @@ import org.springframework.data.couchbase.core.mapping.event.BeforeConvertEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.BeforeDeleteEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.BeforeSaveEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.CouchbaseMappingEvent;
|
||||
import org.springframework.data.couchbase.core.view.Consistency;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
@@ -100,6 +103,9 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP
|
||||
|
||||
protected final MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext;
|
||||
|
||||
//default value is in case the template isn't constructed through configuration mechanisms that use the setter.
|
||||
private Consistency configuredConsistency = Consistency.DEFAULT_CONSISTENCY;
|
||||
|
||||
public CouchbaseTemplate(final ClusterInfo clusterInfo, final Bucket client) {
|
||||
this(clusterInfo, client, null, null);
|
||||
}
|
||||
@@ -576,4 +582,13 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP
|
||||
public CouchbaseConverter getConverter() {
|
||||
return this.converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consistency getDefaultConsistency() {
|
||||
return configuredConsistency;
|
||||
}
|
||||
|
||||
public void setDefaultConsistency(Consistency consistency) {
|
||||
this.configuredConsistency = consistency;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.core.view;
|
||||
|
||||
import com.couchbase.client.java.query.consistency.ScanConsistency;
|
||||
import com.couchbase.client.java.view.Stale;
|
||||
|
||||
/**
|
||||
* Enumeration of different consistency configurations to be used by the queries generated by the
|
||||
* framework.
|
||||
*
|
||||
* Each consistency can be translated to a {@link Stale} (for the {@link #viewConsistency() views})
|
||||
* and {@link ScanConsistency} (for the {@link #n1qlConsistency() N1QL queries}).
|
||||
*
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public enum Consistency {
|
||||
|
||||
/** READ_YOUR_OWN_WRITES is {@link Stale#FALSE} and {@link ScanConsistency#STATEMENT_PLUS} */
|
||||
READ_YOUR_OWN_WRITES(Stale.FALSE, ScanConsistency.STATEMENT_PLUS),
|
||||
/** STRONGLY_CONSISTENT is {@link Stale#FALSE} and {@link ScanConsistency#REQUEST_PLUS} */
|
||||
STRONGLY_CONSISTENT(Stale.FALSE, ScanConsistency.REQUEST_PLUS),
|
||||
/** UPDATE_AFTER is {@link Stale#UPDATE_AFTER} and {@link ScanConsistency#NOT_BOUNDED} */
|
||||
UPDATE_AFTER(Stale.UPDATE_AFTER, ScanConsistency.NOT_BOUNDED),
|
||||
/** EVENTUALLY_CONSISTENT is {@link Stale#TRUE} and {@link ScanConsistency#NOT_BOUNDED} */
|
||||
EVENTUALLY_CONSISTENT(Stale.TRUE, ScanConsistency.NOT_BOUNDED);
|
||||
|
||||
/**
|
||||
* The static default Consistency ({@link #UPDATE_AFTER}).
|
||||
*/
|
||||
public static final Consistency DEFAULT_CONSISTENCY = UPDATE_AFTER;
|
||||
|
||||
private final Stale viewConsistency;
|
||||
private final ScanConsistency n1qlConsistency;
|
||||
|
||||
Consistency(Stale viewConsistency, ScanConsistency n1qlConsistency) {
|
||||
this.viewConsistency = viewConsistency;
|
||||
this.n1qlConsistency = n1qlConsistency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Stale view consistency} corresponding to this {@link Consistency}.
|
||||
*
|
||||
* @return the view consistency.
|
||||
*/
|
||||
public Stale viewConsistency() {
|
||||
return viewConsistency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ScanConsistency N1QL consistency} corresponding to this {@link Consistency}.
|
||||
*
|
||||
* @return the N1QL consistency.
|
||||
*/
|
||||
public ScanConsistency n1qlConsistency() {
|
||||
return n1qlConsistency;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,9 @@ import java.util.List;
|
||||
|
||||
import com.couchbase.client.java.document.json.JsonArray;
|
||||
import com.couchbase.client.java.query.Query;
|
||||
import com.couchbase.client.java.query.QueryParams;
|
||||
import com.couchbase.client.java.query.Statement;
|
||||
import com.couchbase.client.java.query.consistency.ScanConsistency;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -57,18 +59,20 @@ public abstract class AbstractN1qlBasedQuery implements RepositoryQuery {
|
||||
Statement statement = getStatement(accessor);
|
||||
JsonArray queryPlaceholderValues = getPlaceholderValues(accessor);
|
||||
|
||||
Query query = buildQuery(statement, queryPlaceholderValues);
|
||||
Query query = buildQuery(statement, queryPlaceholderValues,
|
||||
getCouchbaseOperations().getDefaultConsistency().n1qlConsistency());
|
||||
return executeDependingOnType(query, queryMethod, queryMethod.isPageQuery(), queryMethod.isModifyingQuery(),
|
||||
queryMethod.isSliceQuery());
|
||||
}
|
||||
|
||||
protected static Query buildQuery(Statement statement, JsonArray queryPlaceholderValues) {
|
||||
protected static Query buildQuery(Statement statement, JsonArray queryPlaceholderValues, ScanConsistency scanConsistency) {
|
||||
QueryParams queryParams = QueryParams.build().consistency(scanConsistency);
|
||||
Query query;
|
||||
if (!queryPlaceholderValues.isEmpty()) {
|
||||
query = Query.parameterized(statement, queryPlaceholderValues);
|
||||
query = Query.parameterized(statement, queryPlaceholderValues, queryParams);
|
||||
}
|
||||
else {
|
||||
query = Query.simple(statement);
|
||||
query = Query.simple(statement, queryParams);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
|
||||
@@ -68,7 +68,8 @@ public class ViewBasedCouchbaseQuery implements RepositoryQuery {
|
||||
boolean isReduce = methodName.startsWith("count");
|
||||
String viewName = StringUtils.uncapitalize(methodName.replaceFirst("find|count", ""));
|
||||
|
||||
ViewQuery simpleQuery = ViewQuery.from(designDoc, viewName);
|
||||
ViewQuery simpleQuery = ViewQuery.from(designDoc, viewName)
|
||||
.stale(operations.getDefaultConsistency().viewConsistency());
|
||||
if (isReduce) {
|
||||
simpleQuery.reduce(isReduce);
|
||||
return executeReduce(simpleQuery, designDoc, viewName);
|
||||
@@ -80,7 +81,8 @@ public class ViewBasedCouchbaseQuery implements RepositoryQuery {
|
||||
protected Object deriveAndExecute(Object[] runtimeParams) {
|
||||
String designDoc = designDocName(method);
|
||||
String viewName = method.getViewAnnotation().viewName();
|
||||
ViewQuery baseQuery = ViewQuery.from(designDoc, viewName);
|
||||
ViewQuery baseQuery = ViewQuery.from(designDoc, viewName)
|
||||
.stale(operations.getDefaultConsistency().viewConsistency());
|
||||
try {
|
||||
PartTree tree = new PartTree(method.getName(), method.getEntityInformation().getJavaType());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user