DATACOUCH-273 - Integrate Data Commons Java 8 upgrade branch.
Replace PersistentEntity.doWithProperties(…) and .doWithAssociations(…) with stream processing using PersistentEntity.getPersistentProperties() and PersistentEntity.getAssociations().
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -23,6 +23,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
@@ -86,6 +87,7 @@ import static org.springframework.data.couchbase.core.support.TemplateUtils.SELE
|
||||
* @author Oliver Gierke
|
||||
* @author Simon Baslé
|
||||
* @author Young-Gu Chae
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventPublisherAware {
|
||||
|
||||
@@ -290,7 +292,7 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP
|
||||
|
||||
@Override
|
||||
public <T> T findById(final String id, Class<T> entityClass) {
|
||||
final CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
final CouchbasePersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(entityClass);
|
||||
RawJsonDocument result = execute(new BucketCallback<RawJsonDocument>() {
|
||||
@Override
|
||||
public RawJsonDocument doInBucket() {
|
||||
@@ -573,9 +575,9 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP
|
||||
ensureNotIterable(objectToPersist);
|
||||
|
||||
final ConvertingPropertyAccessor accessor = getPropertyAccessor(objectToPersist);
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(objectToPersist.getClass());
|
||||
final CouchbasePersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
final Long version = versionProperty != null ? accessor.getProperty(versionProperty, Long.class) : null;
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(objectToPersist.getClass());
|
||||
final Optional<CouchbasePersistentProperty> versionProperty = persistentEntity.getVersionProperty();
|
||||
final Long version = versionProperty.flatMap(p -> accessor.getProperty(p, Long.class)).orElse(null);
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<Object>(objectToPersist));
|
||||
final CouchbaseDocument converted = new CouchbaseDocument();
|
||||
@@ -588,7 +590,7 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP
|
||||
Document<String> doc = encodeAndWrap(converted, version);
|
||||
Document<String> storedDoc;
|
||||
//We will check version only if required
|
||||
boolean versionPresent = versionProperty != null;
|
||||
boolean versionPresent = versionProperty.isPresent();
|
||||
//If version is not set - assumption that document is new, otherwise updating
|
||||
boolean existingDocument = version != null && version > 0L;
|
||||
try {
|
||||
@@ -614,9 +616,9 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP
|
||||
break;
|
||||
}
|
||||
|
||||
if (persistentEntity.hasVersionProperty() && storedDoc != null && storedDoc.cas() != 0) {
|
||||
if (storedDoc != null && storedDoc.cas() != 0) {
|
||||
//inject new cas into the bean
|
||||
accessor.setProperty(versionProperty, storedDoc.cas());
|
||||
versionProperty.ifPresent(p -> accessor.setProperty(p, Optional.ofNullable(storedDoc.cas())));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -685,16 +687,14 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP
|
||||
Object readEntity = converter.read(entityClass, (CouchbaseDocument) decodeAndUnwrap(data, converted));
|
||||
|
||||
final ConvertingPropertyAccessor accessor = getPropertyAccessor(readEntity);
|
||||
CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(readEntity.getClass());
|
||||
if (persistentEntity.hasVersionProperty()) {
|
||||
accessor.setProperty(persistentEntity.getVersionProperty(), data.cas());
|
||||
}
|
||||
CouchbasePersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(readEntity.getClass());
|
||||
persistentEntity.getVersionProperty().ifPresent(p -> accessor.setProperty(p, Optional.ofNullable(data.cas())));
|
||||
|
||||
return (T) readEntity;
|
||||
}
|
||||
|
||||
private final ConvertingPropertyAccessor getPropertyAccessor(Object source) {
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(source.getClass());
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(source.getClass());
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(source);
|
||||
|
||||
return new ConvertingPropertyAccessor(accessor, converter.getConversionService());
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.data.couchbase.core;
|
||||
import static org.springframework.data.couchbase.core.CouchbaseTemplate.ensureNotIterable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.couchbase.client.java.AsyncBucket;
|
||||
import com.couchbase.client.java.Bucket;
|
||||
@@ -47,6 +48,7 @@ import rx.Observable;
|
||||
/**
|
||||
* RxJavaCouchbaseTemplate implements operations using rxjava1 observables
|
||||
* @author Subhashni Balakrishnan
|
||||
* @author Mark Paluch
|
||||
* @since 3.0
|
||||
*/
|
||||
public class RxJavaCouchbaseTemplate implements RxJavaCouchbaseOperations {
|
||||
@@ -149,7 +151,7 @@ public class RxJavaCouchbaseTemplate implements RxJavaCouchbaseOperations {
|
||||
}
|
||||
|
||||
private final ConvertingPropertyAccessor getPropertyAccessor(Object source) {
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(source.getClass());
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(source.getClass());
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(source);
|
||||
|
||||
return new ConvertingPropertyAccessor(accessor, converter.getConversionService());
|
||||
@@ -160,9 +162,9 @@ public class RxJavaCouchbaseTemplate implements RxJavaCouchbaseOperations {
|
||||
ensureNotIterable(objectToPersist);
|
||||
|
||||
final ConvertingPropertyAccessor accessor = getPropertyAccessor(objectToPersist);
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(objectToPersist.getClass());
|
||||
final CouchbasePersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
final Long version = versionProperty != null ? accessor.getProperty(versionProperty, Long.class) : null;
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(objectToPersist.getClass());
|
||||
Optional<CouchbasePersistentProperty> versionProperty = persistentEntity.getVersionProperty();
|
||||
final Long version = versionProperty.flatMap(p -> accessor.getProperty(p, Long.class)).orElse(null);
|
||||
|
||||
final CouchbaseDocument converted = new CouchbaseDocument();
|
||||
converter.write(objectToPersist, converted);
|
||||
@@ -180,9 +182,9 @@ public class RxJavaCouchbaseTemplate implements RxJavaCouchbaseOperations {
|
||||
.doOnError(e -> TemplateUtils.translateError(e));
|
||||
} else {
|
||||
final ConvertingPropertyAccessor accessor = getPropertyAccessor(objectToRemove);
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(objectToRemove.getClass());
|
||||
final CouchbasePersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
final Long version = versionProperty != null ? accessor.getProperty(versionProperty, Long.class) : null;
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(objectToRemove.getClass());
|
||||
final Optional<CouchbasePersistentProperty> versionProperty = persistentEntity.getVersionProperty();
|
||||
final Long version = versionProperty.flatMap(p -> accessor.getProperty(p, Long.class)).orElse(null);
|
||||
|
||||
final CouchbaseDocument converted = new CouchbaseDocument();
|
||||
converter.write(objectToRemove, converted);
|
||||
@@ -220,7 +222,7 @@ public class RxJavaCouchbaseTemplate implements RxJavaCouchbaseOperations {
|
||||
|
||||
@Override
|
||||
public <T> Observable<T> findById(String id, Class<T> entityClass) {
|
||||
final CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
final CouchbasePersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(entityClass);
|
||||
if (entity.isTouchOnRead()) {
|
||||
return client.getAndTouch(id, entity.getExpiry(), RawJsonDocument.class)
|
||||
.switchIfEmpty(Observable.just(null))
|
||||
@@ -336,10 +338,8 @@ public class RxJavaCouchbaseTemplate implements RxJavaCouchbaseOperations {
|
||||
Object readEntity = converter.read(entityClass, (CouchbaseDocument) decodeAndUnwrap(data, converted));
|
||||
|
||||
final ConvertingPropertyAccessor accessor = getPropertyAccessor(readEntity);
|
||||
CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(readEntity.getClass());
|
||||
if (persistentEntity.hasVersionProperty()) {
|
||||
accessor.setProperty(persistentEntity.getVersionProperty(), data.cas());
|
||||
}
|
||||
CouchbasePersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(readEntity.getClass());
|
||||
persistentEntity.getVersionProperty().ifPresent(p -> accessor.setProperty(p, Optional.ofNullable(data.cas())));
|
||||
|
||||
return (T) readEntity;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -19,11 +19,15 @@ package org.springframework.data.couchbase.core.convert;
|
||||
import org.springframework.data.convert.DefaultTypeMapper;
|
||||
import org.springframework.data.convert.TypeAliasAccessor;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.mapping.Alias;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The Couchbase Type Mapper.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class DefaultCouchbaseTypeMapper extends DefaultTypeMapper<CouchbaseDocument> implements CouchbaseTypeMapper {
|
||||
|
||||
@@ -58,8 +62,8 @@ public class DefaultCouchbaseTypeMapper extends DefaultTypeMapper<CouchbaseDocum
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readAliasFrom(final CouchbaseDocument source) {
|
||||
return source.get(typeKey);
|
||||
public Alias readAliasFrom(final CouchbaseDocument source) {
|
||||
return Alias.ofOptional(Optional.ofNullable(source.get(typeKey)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.couchbase.client.java.repository.annotation.Field;
|
||||
|
||||
@@ -201,10 +202,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
return (R) readMap(typeToUse, source, parent);
|
||||
}
|
||||
|
||||
CouchbasePersistentEntity<R> entity = (CouchbasePersistentEntity<R>) mappingContext.getPersistentEntity(typeToUse);
|
||||
if (entity == null) {
|
||||
throw new MappingException("No mapping metadata found for " + rawType.getName());
|
||||
}
|
||||
CouchbasePersistentEntity<R> entity = (CouchbasePersistentEntity<R>) mappingContext.getRequiredPersistentEntity(typeToUse);
|
||||
return read(entity, source, parent);
|
||||
}
|
||||
|
||||
@@ -226,30 +224,27 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
final R instance = instantiator.createInstance(entity, provider);
|
||||
final ConvertingPropertyAccessor accessor = getPropertyAccessor(instance);
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CouchbasePersistentProperty>() {
|
||||
@Override
|
||||
public void doWithPersistentProperty(final CouchbasePersistentProperty prop) {
|
||||
if (!doesPropertyExistInSource(prop) || entity.isConstructorArgument(prop)) {
|
||||
return;
|
||||
}
|
||||
Object obj = prop.isIdProperty() ? source.getId() : getValueInternal(prop, source, instance);
|
||||
accessor.setProperty(prop, obj);
|
||||
entity.getPersistentProperties().filter(prop -> {
|
||||
|
||||
if (!(prop.isIdProperty() || source.containsKey(prop.getFieldName())) || entity.isConstructorArgument(prop)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean doesPropertyExistInSource(final CouchbasePersistentProperty property) {
|
||||
return property.isIdProperty() || source.containsKey(property.getFieldName());
|
||||
}
|
||||
return true;
|
||||
}).forEach(prop -> {
|
||||
|
||||
Optional<Object> obj = prop.isIdProperty() ? Optional.ofNullable(source.getId()) : getValueInternal(prop, source, instance);
|
||||
accessor.setProperty(prop, obj);
|
||||
});
|
||||
|
||||
entity.doWithAssociations(new AssociationHandler<CouchbasePersistentProperty>() {
|
||||
@Override
|
||||
public void doWithAssociation(final Association<CouchbasePersistentProperty> association) {
|
||||
CouchbasePersistentProperty inverseProp = association.getInverse();
|
||||
Object obj = getValueInternal(inverseProp, source, instance);
|
||||
accessor.setProperty(inverseProp, obj);
|
||||
}
|
||||
entity.getAssociations().forEach(association -> {
|
||||
CouchbasePersistentProperty inverseProp = association.getInverse();
|
||||
Optional<Object> obj = getValueInternal(inverseProp, source, instance);
|
||||
accessor.setProperty(inverseProp, obj);
|
||||
|
||||
});
|
||||
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -261,7 +256,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
* @param parent the optional parent.
|
||||
* @return the actual property value.
|
||||
*/
|
||||
protected Object getValueInternal(final CouchbasePersistentProperty property, final CouchbaseDocument source,
|
||||
protected Optional<Object> getValueInternal(final CouchbasePersistentProperty property, final CouchbaseDocument source,
|
||||
final Object parent) {
|
||||
return new CouchbasePropertyValueProvider(source, spELContext, parent).getPropertyValue(property);
|
||||
}
|
||||
@@ -280,7 +275,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
final DefaultSpELExpressionEvaluator evaluator, final Object parent) {
|
||||
CouchbasePropertyValueProvider provider = new CouchbasePropertyValueProvider(source, evaluator, parent);
|
||||
PersistentEntityParameterValueProvider<CouchbasePersistentProperty> parameterProvider =
|
||||
new PersistentEntityParameterValueProvider<CouchbasePersistentProperty>(entity, provider, parent);
|
||||
new PersistentEntityParameterValueProvider<CouchbasePersistentProperty>(entity, provider, Optional.ofNullable(parent));
|
||||
|
||||
return new ConverterAwareSpELExpressionParameterValueProvider(evaluator, conversionService, parameterProvider,
|
||||
parent);
|
||||
@@ -304,16 +299,13 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
Map<String, Object> sourceMap = source.getPayload();
|
||||
|
||||
for (Map.Entry<String, Object> entry : sourceMap.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
TypeInformation<?> keyTypeInformation = type.getComponentType();
|
||||
if (keyTypeInformation != null) {
|
||||
Class<?> keyType = keyTypeInformation.getType();
|
||||
key = conversionService.convert(key, keyType);
|
||||
}
|
||||
Object key = type.getComponentType().map(TypeInformation::getType) //
|
||||
.map(keyType -> (Object) conversionService.convert(entry.getKey(), keyType)) //
|
||||
.orElse(entry.getKey());
|
||||
|
||||
TypeInformation<?> valueType = type.getMapValueType();
|
||||
TypeInformation<?> valueType = type.getMapValueType().orElse(null);
|
||||
if (value instanceof CouchbaseDocument) {
|
||||
map.put(key, read(valueType, (CouchbaseDocument) value, parent));
|
||||
} else if (value instanceof CouchbaseList) {
|
||||
@@ -406,7 +398,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
throw new IllegalArgumentException("Root Document must be either CouchbaseDocument or Map.");
|
||||
}
|
||||
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(source.getClass());
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(source.getClass()).orElse(null);
|
||||
writeInternal(source, target, entity);
|
||||
addCustomTypeKeyIfNecessary(typeHint, source, target);
|
||||
}
|
||||
@@ -443,45 +435,49 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
}
|
||||
|
||||
final ConvertingPropertyAccessor accessor = getPropertyAccessor(source);
|
||||
final CouchbasePersistentProperty idProperty = entity.getIdProperty();
|
||||
final CouchbasePersistentProperty versionProperty = entity.getVersionProperty();
|
||||
final Optional<CouchbasePersistentProperty> idProperty = entity.getIdProperty();
|
||||
final Optional<CouchbasePersistentProperty> versionProperty = entity.getVersionProperty();
|
||||
|
||||
if (idProperty != null && target.getId() == null) {
|
||||
String id = accessor.getProperty(idProperty, String.class);
|
||||
target.setId(id);
|
||||
if (target.getId() == null) {
|
||||
idProperty.ifPresent(id -> {
|
||||
target.setId(accessor.getProperty(id, String.class).orElse(null));
|
||||
});
|
||||
}
|
||||
target.setExpiration(entity.getExpiry());
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CouchbasePersistentProperty>() {
|
||||
@Override
|
||||
public void doWithPersistentProperty(final CouchbasePersistentProperty prop) {
|
||||
if (prop.equals(idProperty) || (versionProperty != null && prop.equals(versionProperty))) {
|
||||
return;
|
||||
} else if(enableStrictFieldChecking && !prop.isAnnotationPresent(Field.class)){
|
||||
return;
|
||||
}
|
||||
entity.getPersistentProperties().filter(prop -> {
|
||||
|
||||
Object propertyObj = accessor.getProperty(prop, prop.getType());
|
||||
if (null != propertyObj) {
|
||||
if (!conversions.isSimpleType(propertyObj.getClass())) {
|
||||
writePropertyInternal(propertyObj, target, prop);
|
||||
} else {
|
||||
writeSimpleInternal(propertyObj, target, prop.getFieldName());
|
||||
}
|
||||
}
|
||||
if (idProperty.filter(prop::equals).isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (versionProperty.filter(prop::equals).isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enableStrictFieldChecking && !prop.isAnnotationPresent(Field.class)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).forEach(prop -> {
|
||||
Optional<Object> propertyObj = accessor.getProperty(prop, (Class) prop.getType());
|
||||
propertyObj.ifPresent(o -> {
|
||||
if (!conversions.isSimpleType(o.getClass())) {
|
||||
writePropertyInternal(o, target, prop);
|
||||
} else {
|
||||
writeSimpleInternal(o, target, prop.getFieldName());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
entity.doWithAssociations(new AssociationHandler<CouchbasePersistentProperty>() {
|
||||
@Override
|
||||
public void doWithAssociation(final Association<CouchbasePersistentProperty> association) {
|
||||
CouchbasePersistentProperty inverseProp = association.getInverse();
|
||||
Class<?> type = inverseProp.getType();
|
||||
Object propertyObj = accessor.getProperty(inverseProp, type);
|
||||
if (null != propertyObj) {
|
||||
writePropertyInternal(propertyObj, target, inverseProp);
|
||||
}
|
||||
}
|
||||
|
||||
entity.getAssociations().forEach(association -> {
|
||||
CouchbasePersistentProperty inverseProp = association.getInverse();
|
||||
Class<?> type = inverseProp.getType();
|
||||
Optional<Object> propertyObj = accessor.getProperty(inverseProp, (Class) type);
|
||||
propertyObj.ifPresent(o -> {
|
||||
writePropertyInternal(o, target, inverseProp);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
@@ -526,7 +522,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
addCustomTypeKeyIfNecessary(type, source, propertyDoc);
|
||||
|
||||
CouchbasePersistentEntity<?> entity = isSubtype(prop.getType(), source.getClass()) ? mappingContext
|
||||
.getPersistentEntity(source.getClass()) : mappingContext.getPersistentEntity(type);
|
||||
.getRequiredPersistentEntity(source.getClass()) : mappingContext.getRequiredPersistentEntity(type);
|
||||
writeInternal(source, propertyDoc, entity);
|
||||
target.put(name, propertyDoc);
|
||||
}
|
||||
@@ -568,7 +564,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
target.put(simpleKey, writeCollectionInternal(asCollection(val), new CouchbaseList(conversions.getSimpleTypeHolder()), type.getMapValueType()));
|
||||
} else {
|
||||
CouchbaseDocument embeddedDoc = new CouchbaseDocument();
|
||||
TypeInformation<?> valueTypeInfo = type.isMap() ? type.getMapValueType() : ClassTypeInformation.OBJECT;
|
||||
TypeInformation<?> valueTypeInfo = type.isMap() ? type.getMapValueType().orElse(ClassTypeInformation.OBJECT) : ClassTypeInformation.OBJECT;
|
||||
writeInternal(val, embeddedDoc, valueTypeInfo);
|
||||
target.put(simpleKey, embeddedDoc);
|
||||
}
|
||||
@@ -588,7 +584,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
* @return the created couchbase list.
|
||||
*/
|
||||
private CouchbaseList createCollection(final Collection<?> collection, final CouchbasePersistentProperty prop) {
|
||||
return writeCollectionInternal(collection, new CouchbaseList(conversions.getSimpleTypeHolder()), prop.getTypeInformation());
|
||||
return writeCollectionInternal(collection, new CouchbaseList(conversions.getSimpleTypeHolder()), Optional.of(prop.getTypeInformation()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -600,8 +596,9 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
* @return the created couchbase list.
|
||||
*/
|
||||
private CouchbaseList writeCollectionInternal(final Collection<?> source, final CouchbaseList target,
|
||||
final TypeInformation<?> type) {
|
||||
TypeInformation<?> componentType = type == null ? null : type.getComponentType();
|
||||
final Optional<TypeInformation<?>> type) {
|
||||
|
||||
Optional<TypeInformation<?>> componentType = type.flatMap(TypeInformation::getComponentType);
|
||||
|
||||
for (Object element : source) {
|
||||
Class<?> elementType = element == null ? null : element.getClass();
|
||||
@@ -611,8 +608,10 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
} else if (element instanceof Collection || elementType.isArray()) {
|
||||
target.put(writeCollectionInternal(asCollection(element), new CouchbaseList(conversions.getSimpleTypeHolder()), componentType));
|
||||
} else {
|
||||
|
||||
TypeInformation<?> typeInformation = componentType.orElse(null);
|
||||
CouchbaseDocument embeddedDoc = new CouchbaseDocument();
|
||||
writeInternal(element, embeddedDoc, componentType);
|
||||
writeInternal(element, embeddedDoc, typeInformation);
|
||||
target.put(embeddedDoc);
|
||||
}
|
||||
|
||||
@@ -641,7 +640,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
|
||||
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>() : CollectionFactory
|
||||
.createCollection(collectionType, source.size(false));
|
||||
TypeInformation<?> componentType = targetType.getComponentType();
|
||||
TypeInformation<?> componentType = targetType.getComponentType().orElse(null);
|
||||
Class<?> rawComponentType = componentType == null ? null : componentType.getType();
|
||||
|
||||
for (int i = 0; i < source.size(false); i++) {
|
||||
@@ -756,7 +755,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
}
|
||||
|
||||
private ConvertingPropertyAccessor getPropertyAccessor(Object source) {
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(source.getClass());
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(source.getClass());
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(source);
|
||||
|
||||
return new ConvertingPropertyAccessor(accessor, conversionService);
|
||||
@@ -799,18 +798,18 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> R getPropertyValue(final CouchbasePersistentProperty property) {
|
||||
String expression = property.getSpelExpression();
|
||||
Object value = expression != null ? evaluator.evaluate(expression) : source.get(property.getFieldName());
|
||||
public <R> Optional<R> getPropertyValue(final CouchbasePersistentProperty property) {
|
||||
|
||||
Object value = property.getSpelExpression().map(evaluator::evaluate).orElseGet(() -> source.get(property.getFieldName()));
|
||||
|
||||
if (property.isIdProperty()) {
|
||||
return (R) source.getId();
|
||||
return Optional.ofNullable((R) source.getId());
|
||||
}
|
||||
if (value == null) {
|
||||
return null;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return readValue(value, property.getTypeInformation(), parent);
|
||||
return Optional.ofNullable(readValue(value, property.getTypeInformation(), parent));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -32,9 +32,10 @@ import java.util.concurrent.TimeUnit;
|
||||
* The representation of a persistent entity.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class BasicCouchbasePersistentEntity<T> extends BasicPersistentEntity<T, CouchbasePersistentProperty>
|
||||
implements CouchbasePersistentEntity<T>, EnvironmentAware {
|
||||
implements CouchbasePersistentEntity<T>, EnvironmentAware {
|
||||
|
||||
private Environment environment;
|
||||
|
||||
@@ -74,8 +75,12 @@ public class BasicCouchbasePersistentEntity<T> extends BasicPersistentEntity<T,
|
||||
}
|
||||
|
||||
//check existing ID vs new candidate
|
||||
boolean currentCbId = this.getIdProperty().isAnnotationPresent(Id.class);
|
||||
boolean currentSpringId = this.getIdProperty().isAnnotationPresent(org.springframework.data.annotation.Id.class);
|
||||
boolean currentCbId = this.getIdProperty()
|
||||
.map(couchbasePersistentProperty -> couchbasePersistentProperty.isAnnotationPresent(Id.class))
|
||||
.orElse(false);
|
||||
boolean currentSpringId = this.getIdProperty()
|
||||
.map(couchbasePersistentProperty -> couchbasePersistentProperty.isAnnotationPresent(org.springframework.data.annotation.Id.class))
|
||||
.orElse(false);
|
||||
boolean candidateCbId = property.isAnnotationPresent(Id.class);
|
||||
boolean candidateSpringId = property.isAnnotationPresent(org.springframework.data.annotation.Id.class);
|
||||
|
||||
@@ -137,7 +142,7 @@ public class BasicCouchbasePersistentEntity<T> extends BasicPersistentEntity<T,
|
||||
@Override
|
||||
public boolean isTouchOnRead() {
|
||||
org.springframework.data.couchbase.core.mapping.Document annotation = getType().getAnnotation(
|
||||
org.springframework.data.couchbase.core.mapping.Document.class);
|
||||
org.springframework.data.couchbase.core.mapping.Document.class);
|
||||
return annotation == null ? false : annotation.touchOnRead() && getExpiry() > 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -16,19 +16,19 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import com.couchbase.client.java.repository.annotation.Field;
|
||||
import com.couchbase.client.java.repository.annotation.Id;
|
||||
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Implements annotated property representations of a given {@link com.couchbase.client.java.repository.annotation.Field} instance.
|
||||
* <p/>
|
||||
@@ -36,27 +36,27 @@ import org.springframework.util.StringUtils;
|
||||
* supports overriding of the actual property name by providing custom annotations.</p>
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class BasicCouchbasePersistentProperty
|
||||
extends AnnotationBasedPersistentProperty<CouchbasePersistentProperty>
|
||||
implements CouchbasePersistentProperty {
|
||||
extends AnnotationBasedPersistentProperty<CouchbasePersistentProperty>
|
||||
implements CouchbasePersistentProperty {
|
||||
|
||||
private final FieldNamingStrategy fieldNamingStrategy;
|
||||
|
||||
/**
|
||||
* Create a new instance of the BasicCouchbasePersistentProperty class.
|
||||
*
|
||||
* @param field the field of the original reflection.
|
||||
* @param propertyDescriptor the PropertyDescriptor.
|
||||
* @param owner the original owner of the property.
|
||||
* @param property the PropertyDescriptor.
|
||||
* @param owner the original owner of the property.
|
||||
* @param simpleTypeHolder the type holder.
|
||||
*/
|
||||
public BasicCouchbasePersistentProperty(final Field field, final PropertyDescriptor propertyDescriptor,
|
||||
public BasicCouchbasePersistentProperty(Property property,
|
||||
final CouchbasePersistentEntity<?> owner, final SimpleTypeHolder simpleTypeHolder,
|
||||
final FieldNamingStrategy fieldNamingStrategy) {
|
||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
||||
super(property, owner, simpleTypeHolder);
|
||||
this.fieldNamingStrategy = fieldNamingStrategy == null ? PropertyNameFieldNamingStrategy.INSTANCE
|
||||
: fieldNamingStrategy;
|
||||
: fieldNamingStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,21 +75,20 @@ public class BasicCouchbasePersistentProperty
|
||||
*/
|
||||
@Override
|
||||
public String getFieldName() {
|
||||
com.couchbase.client.java.repository.annotation.Field annotation = getField().
|
||||
getAnnotation(com.couchbase.client.java.repository.annotation.Field.class);
|
||||
Optional<Field> annotation = findAnnotation(com.couchbase.client.java.repository.annotation.Field.class);
|
||||
|
||||
if (annotation != null && StringUtils.hasText(annotation.value())) {
|
||||
return annotation.value();
|
||||
}
|
||||
return annotation.map(Field::value).filter(StringUtils::hasText).orElseGet(() -> {
|
||||
|
||||
String fieldName = fieldNamingStrategy.getFieldName(this);
|
||||
String fieldName = fieldNamingStrategy.getFieldName(this);
|
||||
|
||||
if (!StringUtils.hasText(fieldName)) {
|
||||
throw new MappingException(String.format("Invalid (null or empty) field name returned for property %s by %s!",
|
||||
this, fieldNamingStrategy.getClass()));
|
||||
}
|
||||
if (!StringUtils.hasText(fieldName)) {
|
||||
throw new MappingException(String.format("Invalid (null or empty) field name returned for property %s by %s!",
|
||||
this, fieldNamingStrategy.getClass()));
|
||||
}
|
||||
|
||||
return fieldName;
|
||||
});
|
||||
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
// DATACOUCH-145: allows SDK's @Id annotation to be used
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -16,14 +16,12 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
@@ -83,16 +81,15 @@ public class CouchbaseMappingContext
|
||||
/**
|
||||
* Creates a concrete property based on the field information and entity.
|
||||
*
|
||||
* @param field the reflection on the field to be used as a property.
|
||||
* @param descriptor the property descriptor.
|
||||
* @param property the property descriptor.
|
||||
* @param owner the entity which owns the property.
|
||||
* @param simpleTypeHolder the type holder.
|
||||
* @return the constructed property.
|
||||
*/
|
||||
@Override
|
||||
protected CouchbasePersistentProperty createPersistentProperty(final Field field, final PropertyDescriptor descriptor,
|
||||
protected CouchbasePersistentProperty createPersistentProperty(Property property,
|
||||
final BasicCouchbasePersistentEntity<?> owner, final SimpleTypeHolder simpleTypeHolder) {
|
||||
return new BasicCouchbasePersistentProperty(field, descriptor, owner, simpleTypeHolder, fieldNamingStrategy);
|
||||
return new BasicCouchbasePersistentProperty(property, owner, simpleTypeHolder, fieldNamingStrategy);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -23,11 +23,14 @@ import org.springframework.data.auditing.IsNewAwareAuditingHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Event listener to populate auditing related fields on an entity about to be saved.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Simon Baslé
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class AuditingEventListener implements ApplicationListener<BeforeConvertEvent<Object>> {
|
||||
|
||||
@@ -51,6 +54,6 @@ public class AuditingEventListener implements ApplicationListener<BeforeConvertE
|
||||
public void onApplicationEvent(BeforeConvertEvent<Object> event) {
|
||||
|
||||
Object entity = event.getSource();
|
||||
auditingHandlerFactory.getObject().markAudited(entity);
|
||||
auditingHandlerFactory.getObject().markAudited(Optional.of(entity));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -20,6 +20,7 @@ import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.couchbase.core.CouchbaseOperations;
|
||||
@@ -50,7 +51,7 @@ public class CouchbaseRepositoryBean<T> extends CdiRepositoryBean<T> {
|
||||
*/
|
||||
public CouchbaseRepositoryBean(Bean<CouchbaseOperations> operations, Set<Annotation> qualifiers, Class<T> repositoryType,
|
||||
BeanManager beanManager, CustomRepositoryImplementationDetector detector) {
|
||||
super(qualifiers, repositoryType, beanManager, detector);
|
||||
super(qualifiers, repositoryType, beanManager, Optional.of(detector));
|
||||
|
||||
Assert.notNull(operations, "Cannot create repository with 'null' for CouchbaseOperations.");
|
||||
this.couchbaseOperationsBean = operations;
|
||||
@@ -61,11 +62,17 @@ public class CouchbaseRepositoryBean<T> extends CdiRepositoryBean<T> {
|
||||
* @see org.springframework.data.repository.cdi.CdiRepositoryBean#create(javax.enterprise.context.spi.CreationalContext, java.lang.Class, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Object customImplementation) {
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Optional<Object> customImplementation) {
|
||||
|
||||
CouchbaseOperations couchbaseOperations = getDependencyInstance(couchbaseOperationsBean, CouchbaseOperations.class);
|
||||
RepositoryOperationsMapping couchbaseOperationsMapping = new RepositoryOperationsMapping(couchbaseOperations);
|
||||
IndexManager indexManager = new IndexManager();
|
||||
return new CouchbaseRepositoryFactory(couchbaseOperationsMapping, indexManager).getRepository(repositoryType, customImplementation);
|
||||
|
||||
CouchbaseRepositoryFactory factory =
|
||||
new CouchbaseRepositoryFactory(couchbaseOperationsMapping, indexManager);
|
||||
|
||||
return customImplementation.map(o -> factory.getRepository(repositoryType, o))
|
||||
.orElseGet(() -> factory.getRepository(repositoryType));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -20,6 +20,7 @@ import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.couchbase.core.RxJavaCouchbaseOperations;
|
||||
@@ -33,6 +34,7 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* A bean which represents a Couchbase repository.
|
||||
* @author Subhashni Balakrishnan
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ReactiveCouchbaseRepositoryBean<T> extends CdiRepositoryBean<T> {
|
||||
|
||||
@@ -50,22 +52,27 @@ public class ReactiveCouchbaseRepositoryBean<T> extends CdiRepositoryBean<T> {
|
||||
*/
|
||||
public ReactiveCouchbaseRepositoryBean(Bean<RxJavaCouchbaseOperations> reactiveOperations, Set<Annotation> qualifiers, Class<T> repositoryType,
|
||||
BeanManager beanManager, CustomRepositoryImplementationDetector detector) {
|
||||
super(qualifiers, repositoryType, beanManager, detector);
|
||||
super(qualifiers, repositoryType, beanManager, Optional.of(detector));
|
||||
|
||||
Assert.notNull(reactiveOperations, "Cannot create repository with 'null' for ReactiveCouchbaseOperations.");
|
||||
this.reactiveCouchbaseOperationsBean = reactiveOperations;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.cdi.CdiRepositoryBean#create(javax.enterprise.context.spi.CreationalContext, java.lang.Class, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Object customImplementation) {
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Optional<Object> customImplementation) {
|
||||
RxJavaCouchbaseOperations reactiveCouchbaseOperations = getDependencyInstance(reactiveCouchbaseOperationsBean, RxJavaCouchbaseOperations.class);
|
||||
ReactiveRepositoryOperationsMapping reactiveCouchbaseOperationsMapping = new ReactiveRepositoryOperationsMapping(reactiveCouchbaseOperations);
|
||||
IndexManager indexManager = new IndexManager();
|
||||
return new ReactiveCouchbaseRepositoryFactory(reactiveCouchbaseOperationsMapping, indexManager).getRepository(repositoryType, customImplementation);
|
||||
|
||||
ReactiveCouchbaseRepositoryFactory factory = new ReactiveCouchbaseRepositoryFactory(reactiveCouchbaseOperationsMapping, indexManager);
|
||||
|
||||
return customImplementation.map(o -> factory.getRepository(repositoryType, o))
|
||||
.orElseGet(() -> factory.getRepository(repositoryType));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.data.couchbase.repository.query;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.couchbase.client.java.document.json.JsonArray;
|
||||
import com.couchbase.client.java.document.json.JsonObject;
|
||||
@@ -85,7 +86,7 @@ public abstract class AbstractN1qlBasedQuery implements RepositoryQuery {
|
||||
public Object execute(Object[] parameters) {
|
||||
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
|
||||
|
||||
ResultProcessor processor = this.queryMethod.getResultProcessor().withDynamicProjection(accessor);
|
||||
ResultProcessor processor = this.queryMethod.getResultProcessor().withDynamicProjection(Optional.of(accessor));
|
||||
ReturnedType returnedType = processor.getReturnedType();
|
||||
|
||||
Class<?> typeToRead = returnedType.getTypeToRead();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.couchbase.repository.query;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -30,7 +31,7 @@ import com.couchbase.client.java.query.dsl.path.WherePath;
|
||||
/**
|
||||
*
|
||||
* @author Mark Ramach
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class N1qlCountQueryCreator extends N1qlQueryCreator {
|
||||
|
||||
@@ -42,7 +43,7 @@ public class N1qlCountQueryCreator extends N1qlQueryCreator {
|
||||
@Override
|
||||
protected LimitPath complete(Expression criteria, Sort sort) {
|
||||
// Sorting is not allowed on aggregate count queries.
|
||||
return super.complete(criteria, null);
|
||||
return super.complete(criteria, Sort.unsorted());
|
||||
}
|
||||
|
||||
private static class CountParameterAccessor implements ParameterAccessor {
|
||||
@@ -54,14 +55,14 @@ public class N1qlCountQueryCreator extends N1qlQueryCreator {
|
||||
}
|
||||
|
||||
public Pageable getPageable() {
|
||||
return delegate.getPageable() != null ? new CountPageable(delegate.getPageable()) : null;
|
||||
return delegate.getPageable() != Pageable.NONE ? new CountPageable(delegate.getPageable()) : Pageable.NONE;
|
||||
}
|
||||
|
||||
public Sort getSort() {
|
||||
return null;
|
||||
return Sort.unsorted();
|
||||
}
|
||||
|
||||
public Class<?> getDynamicProjection() {
|
||||
public Optional<Class<?>> getDynamicProjection() {
|
||||
return delegate.getDynamicProjection();
|
||||
}
|
||||
|
||||
@@ -95,13 +96,13 @@ public class N1qlCountQueryCreator extends N1qlQueryCreator {
|
||||
return delegate.getPageSize();
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
public long getOffset() {
|
||||
return delegate.getOffset();
|
||||
}
|
||||
|
||||
public Sort getSort() {
|
||||
// Sorting is not allowed on aggregate count queries.
|
||||
return null;
|
||||
return Sort.unsorted();
|
||||
}
|
||||
|
||||
public Pageable next() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -88,6 +88,7 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
* </p>
|
||||
*
|
||||
* @author Simon Baslé
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class N1qlQueryCreator extends AbstractQueryCreator<LimitPath, Expression> {
|
||||
|
||||
@@ -131,14 +132,12 @@ public class N1qlQueryCreator extends AbstractQueryCreator<LimitPath, Expression
|
||||
OrderByPath selectFromWhere = selectFrom.where(whereCriteria);
|
||||
|
||||
//sort of the Pageable takes precedence over the sort in the query name
|
||||
if ((queryMethod.isPageQuery() || queryMethod.isSliceQuery()) && accessor.getPageable() != null) {
|
||||
if ((queryMethod.isPageQuery() || queryMethod.isSliceQuery()) && !Pageable.NONE.equals(accessor.getPageable())) {
|
||||
Pageable pageable = accessor.getPageable();
|
||||
if (pageable.getSort() != null) {
|
||||
sort = pageable.getSort();
|
||||
}
|
||||
}
|
||||
|
||||
if (sort != null) {
|
||||
if (sort.isSorted()) {
|
||||
com.couchbase.client.java.query.dsl.Sort[] cbSorts = N1qlUtils.createSort(sort, converter);
|
||||
return selectFromWhere.orderBy(cbSorts);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ import org.springframework.util.Assert;
|
||||
* @author Subhashni Balakrishnan
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
|
||||
public class PartTreeN1qlBasedQuery extends AbstractN1qlBasedQuery {
|
||||
|
||||
private final PartTree partTree;
|
||||
@@ -87,11 +86,11 @@ public class PartTreeN1qlBasedQuery extends AbstractN1qlBasedQuery {
|
||||
if (queryMethod.isPageQuery()) {
|
||||
Pageable pageable = accessor.getPageable();
|
||||
Assert.notNull(pageable, "Pageable must not be null!");
|
||||
return selectFromWhereOrderBy.limit(pageable.getPageSize()).offset(pageable.getOffset());
|
||||
} else if (queryMethod.isSliceQuery() && accessor.getPageable() != null) {
|
||||
return selectFromWhereOrderBy.limit(pageable.getPageSize()).offset(Math.toIntExact(pageable.getOffset()));
|
||||
} else if (queryMethod.isSliceQuery() && accessor.getPageable() != Pageable.NONE) {
|
||||
Pageable pageable = accessor.getPageable();
|
||||
Assert.notNull(pageable, "Pageable must not be null!");
|
||||
return selectFromWhereOrderBy.limit(pageable.getPageSize() + 1).offset(pageable.getOffset());
|
||||
return selectFromWhereOrderBy.limit(pageable.getPageSize() + 1).offset(Math.toIntExact(pageable.getOffset()));
|
||||
} else if (partTree.isLimiting()) {
|
||||
return selectFromWhereOrderBy.limit(partTree.getMaxResults());
|
||||
} else {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
package org.springframework.data.couchbase.repository.query;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.couchbase.client.java.document.json.JsonValue;
|
||||
import com.couchbase.client.java.query.N1qlQuery;
|
||||
import com.couchbase.client.java.query.Statement;
|
||||
@@ -29,6 +31,7 @@ import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* @author Subhashni Balakrishnan
|
||||
* @author Mark Paluch
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class ReactiveAbstractN1qlBasedQuery implements RepositoryQuery {
|
||||
@@ -49,7 +52,7 @@ public abstract class ReactiveAbstractN1qlBasedQuery implements RepositoryQuery
|
||||
@Override
|
||||
public Object execute(Object[] parameters) {
|
||||
ReactiveCouchbaseParameterAccessor accessor = new ReactiveCouchbaseParameterAccessor(queryMethod, parameters);
|
||||
ResultProcessor processor = this.queryMethod.getResultProcessor().withDynamicProjection(accessor);
|
||||
ResultProcessor processor = this.queryMethod.getResultProcessor().withDynamicProjection(Optional.of(accessor));
|
||||
ReturnedType returnedType = processor.getReturnedType();
|
||||
|
||||
Class<?> typeToRead = returnedType.getTypeToRead();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -69,6 +69,8 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
* </ul>
|
||||
* </p>
|
||||
* Additionally, {@link PartTree#isLimiting()} will trigger usage of {@link SpatialViewQuery#limit(int) limit}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class SpatialViewQueryCreator extends AbstractQueryCreator<SpatialViewQueryCreator.SpatialViewQueryWrapper, SpatialViewQuery> {
|
||||
|
||||
@@ -240,7 +242,7 @@ public class SpatialViewQueryCreator extends AbstractQueryCreator<SpatialViewQue
|
||||
|
||||
@Override
|
||||
protected SpatialViewQueryWrapper complete(SpatialViewQuery criteria, Sort sort) {
|
||||
if (sort != null) {
|
||||
if (sort.isSorted()) {
|
||||
throw new IllegalArgumentException("Sort is not supported on Spatial View queries");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2017 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 static org.springframework.data.couchbase.core.support.TemplateUtils.*;
|
||||
@@ -191,7 +206,7 @@ public class StringBasedN1qlQueryParser {
|
||||
placeholder = placeholder.replaceFirst(":", "");
|
||||
namedValues.put(placeholder, value);
|
||||
} else {
|
||||
namedValues.put(parameter.getName(), value);
|
||||
parameter.getName().ifPresent(name -> namedValues.put(name, value));
|
||||
}
|
||||
}
|
||||
return namedValues;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -53,6 +53,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Simon Baslé
|
||||
* @author Subhashni Balakrishnan
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class StringN1qlBasedQuery extends AbstractN1qlBasedQuery {
|
||||
private final SpelExpressionParser parser;
|
||||
@@ -89,18 +90,20 @@ public class StringN1qlBasedQuery extends AbstractN1qlBasedQuery {
|
||||
String limitByPart = "";
|
||||
|
||||
Sort sort = accessor.getSort();
|
||||
if (sort != null) {
|
||||
if (sort.isSorted()) {
|
||||
com.couchbase.client.java.query.dsl.Sort[] cbSorts = N1qlUtils.createSort(sort, getCouchbaseOperations().getConverter());
|
||||
orderByPart = " " + new DefaultOrderByPath(null).orderBy(cbSorts).toString();
|
||||
}
|
||||
if (queryMethod.isPageQuery()) {
|
||||
Pageable pageable = accessor.getPageable();
|
||||
Assert.notNull(pageable);
|
||||
limitByPart = " " + new DefaultLimitPath(null).limit(pageable.getPageSize()).offset(pageable.getOffset()).toString();
|
||||
Assert.notNull(pageable, "Pageable must not be null!");
|
||||
limitByPart = " " + new DefaultLimitPath(null).limit(pageable.getPageSize())
|
||||
.offset(Math.toIntExact(pageable.getOffset())).toString();
|
||||
} else if (queryMethod.isSliceQuery()) {
|
||||
Pageable pageable = accessor.getPageable();
|
||||
Assert.notNull(pageable);
|
||||
limitByPart = " " + new DefaultLimitPath(null).limit(pageable.getPageSize() + 1).offset(pageable.getOffset()).toString();
|
||||
Assert.notNull(pageable, "Pageable must not be null!");
|
||||
limitByPart = " " + new DefaultLimitPath(null).limit(pageable.getPageSize() + 1)
|
||||
.offset(Math.toIntExact(pageable.getOffset())).toString();
|
||||
}
|
||||
return N1qlQuery.simple(parsedStatement + orderByPart + limitByPart).statement();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -275,7 +275,7 @@ public class ViewQueryCreator extends AbstractQueryCreator<ViewQueryCreator.Deri
|
||||
protected DerivedViewQuery complete(ViewQuery criteria, Sort sort) {
|
||||
boolean descending = false;
|
||||
|
||||
if (sort != null) {
|
||||
if (sort.isSorted()) {
|
||||
int sortCount = 0;
|
||||
Iterator<Sort.Order> it = sort.iterator();
|
||||
while(it.hasNext()) {
|
||||
|
||||
@@ -65,6 +65,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
*
|
||||
* @author Simon Baslé
|
||||
* @author Subhashni Balakrishnan
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class N1qlUtils {
|
||||
|
||||
@@ -107,10 +108,10 @@ public class N1qlUtils {
|
||||
|
||||
if (returnedType != null && returnedType.needsCustomConstruction()) {
|
||||
List<String> properties = returnedType.getInputProperties();
|
||||
CouchbasePersistentEntity<?> entity = converter.getMappingContext().getPersistentEntity(returnedType.getDomainType());
|
||||
CouchbasePersistentEntity<?> entity = converter.getMappingContext().getRequiredPersistentEntity(returnedType.getDomainType());
|
||||
|
||||
for (String property : properties) {
|
||||
expList.add(path(bucket, i(entity.getPersistentProperty(property).getFieldName())));
|
||||
expList.add(path(bucket, i(entity.getRequiredPersistentProperty(property).getFieldName())));
|
||||
}
|
||||
} else {
|
||||
expList.add(path(bucket, "*"));
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.couchbase.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.couchbase.client.java.util.features.CouchbaseFeature;
|
||||
|
||||
@@ -111,12 +112,8 @@ public class CouchbaseRepositoryFactory extends RepositoryFactorySupport {
|
||||
*/
|
||||
@Override
|
||||
public <T, ID extends Serializable> CouchbaseEntityInformation<T, ID> getEntityInformation(final Class<T> domainClass) {
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(domainClass);
|
||||
|
||||
if (entity == null) {
|
||||
throw new MappingException(String.format("Could not lookup mapping metadata for domain class %s!", domainClass.getName()));
|
||||
}
|
||||
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(domainClass);
|
||||
return new MappingCouchbaseEntityInformation<T, ID>((CouchbasePersistentEntity<T>) entity);
|
||||
}
|
||||
|
||||
@@ -206,8 +203,8 @@ public class CouchbaseRepositoryFactory extends RepositoryFactorySupport {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key, EvaluationContextProvider contextProvider) {
|
||||
return new CouchbaseQueryLookupStrategy(contextProvider);
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrategy.Key key, EvaluationContextProvider contextProvider) {
|
||||
return Optional.of(new CouchbaseQueryLookupStrategy(contextProvider));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -105,14 +105,14 @@ public class N1qlCouchbaseRepository<T, ID extends Serializable>
|
||||
|
||||
//apply the sort if available
|
||||
LimitPath limitPath = groupBy;
|
||||
if (pageable.getSort() != null) {
|
||||
if (pageable.getSort().isSorted()) {
|
||||
com.couchbase.client.java.query.dsl.Sort[] orderings = N1qlUtils.createSort(pageable.getSort(),
|
||||
getCouchbaseOperations().getConverter());
|
||||
limitPath = groupBy.orderBy(orderings);
|
||||
}
|
||||
|
||||
//apply the paging
|
||||
Statement pageStatement = limitPath.limit(pageable.getPageSize()).offset(pageable.getOffset());
|
||||
Statement pageStatement = limitPath.limit(pageable.getPageSize()).offset(Math.toIntExact(pageable.getOffset()));
|
||||
|
||||
//fire the query
|
||||
N1qlQuery query = N1qlQuery.simple(pageStatement, N1qlParams.build().consistency(consistency));
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.couchbase.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.couchbase.client.java.util.features.CouchbaseFeature;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -41,7 +42,8 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @Subhashni Balakrishnan
|
||||
* @author Subhashni Balakrishnan
|
||||
* @author Mark Paluch
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ReactiveCouchbaseRepositoryFactory extends ReactiveRepositoryFactorySupport {
|
||||
@@ -96,11 +98,7 @@ public class ReactiveCouchbaseRepositoryFactory extends ReactiveRepositoryFactor
|
||||
*/
|
||||
@Override
|
||||
public <T, ID extends Serializable> CouchbaseEntityInformation<T, ID> getEntityInformation(final Class<T> domainClass) {
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(domainClass);
|
||||
|
||||
if (entity == null) {
|
||||
throw new MappingException(String.format("Could not lookup mapping metadata for domain class %s!", domainClass.getName()));
|
||||
}
|
||||
CouchbasePersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(domainClass);
|
||||
|
||||
return new MappingCouchbaseEntityInformation<T, ID>((CouchbasePersistentEntity<T>) entity);
|
||||
}
|
||||
@@ -192,8 +190,8 @@ public class ReactiveCouchbaseRepositoryFactory extends ReactiveRepositoryFactor
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key, EvaluationContextProvider contextProvider) {
|
||||
return new ReactiveCouchbaseRepositoryFactory.CouchbaseQueryLookupStrategy(contextProvider);
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrategy.Key key, EvaluationContextProvider contextProvider) {
|
||||
return Optional.of(new ReactiveCouchbaseRepositoryFactory.CouchbaseQueryLookupStrategy(contextProvider));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.data.couchbase.repository.support;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.couchbase.client.java.document.json.JsonArray;
|
||||
import com.couchbase.client.java.error.DocumentDoesNotExistException;
|
||||
@@ -100,9 +101,9 @@ public class SimpleCouchbaseRepository<T, ID extends Serializable> implements Co
|
||||
}
|
||||
|
||||
@Override
|
||||
public T findOne(ID id) {
|
||||
public Optional<T> findOne(ID id) {
|
||||
Assert.notNull(id, "The given id must not be null!");
|
||||
return couchbaseOperations.findById(id.toString(), entityInformation.getJavaType());
|
||||
return Optional.ofNullable(couchbaseOperations.findById(id.toString(), entityInformation.getJavaType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user