@@ -16,18 +16,21 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.convert;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseList;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.data.mapping.model.EntityInstantiators;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* An abstract {@link CouchbaseConverter} that provides the basics for the {@link MappingCouchbaseConverter}.
|
||||
@@ -141,19 +144,34 @@ public abstract class AbstractCouchbaseConverter implements CouchbaseConverter,
|
||||
* This convertForWriteIfNeed takes only the value to convert. It cannot access the annotations of the Field being
|
||||
* converted.
|
||||
*
|
||||
* @param value the value to be converted to the class that would actually be stored.
|
||||
* @param inValue the value to be converted to the class that would actually be stored.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Object convertForWriteIfNeeded(Object value) {
|
||||
if (value == null) {
|
||||
public Object convertForWriteIfNeeded(Object inValue) {
|
||||
if (inValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.conversions.getCustomWriteTarget(value.getClass()) //
|
||||
.map(it -> (Object) this.conversionService.convert(value, it)) //
|
||||
.orElseGet(() -> Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value);
|
||||
Object value = this.conversions.getCustomWriteTarget(inValue.getClass()) //
|
||||
.map(it -> (Object) this.conversionService.convert(inValue, it)) //
|
||||
.orElse(inValue);
|
||||
|
||||
Class<?> elementType = value.getClass();
|
||||
|
||||
if (elementType == null || conversions.isSimpleType(elementType)) {
|
||||
value = Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value;
|
||||
} else if (value instanceof Collection || elementType.isArray()) {
|
||||
TypeInformation<?> type = ClassTypeInformation.from(value.getClass());
|
||||
value = ((MappingCouchbaseConverter) this).writeCollectionInternal(MappingCouchbaseConverter.asCollection(value),
|
||||
new CouchbaseList(conversions.getSimpleTypeHolder()), type, null, null);
|
||||
} else {
|
||||
CouchbaseDocument embeddedDoc = new CouchbaseDocument();
|
||||
TypeInformation<?> type = ClassTypeInformation.from(value.getClass());
|
||||
((MappingCouchbaseConverter) this).writeInternalRoot(value, embeddedDoc, type, false, null);
|
||||
value = embeddedDoc;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -169,7 +169,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implem
|
||||
* @param source the source object.
|
||||
* @return the target collection.
|
||||
*/
|
||||
private static Collection<?> asCollection(final Object source) {
|
||||
protected static Collection<?> asCollection(final Object source) {
|
||||
if (source instanceof Collection) {
|
||||
return (Collection<?>) source;
|
||||
}
|
||||
@@ -459,7 +459,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implem
|
||||
* @param property will be null for the root
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void writeInternalRoot(final Object source, CouchbaseDocument target, TypeInformation<?> typeHint,
|
||||
public void writeInternalRoot(final Object source, CouchbaseDocument target, TypeInformation<?> typeHint,
|
||||
boolean withId, CouchbasePersistentProperty property) {
|
||||
if (source == null) {
|
||||
return;
|
||||
@@ -759,7 +759,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implem
|
||||
* @param target the target document.
|
||||
* @return the created couchbase list.
|
||||
*/
|
||||
private CouchbaseList writeCollectionInternal(final Collection<?> source, final CouchbaseList target,
|
||||
public CouchbaseList writeCollectionInternal(final Collection<?> source, final CouchbaseList target,
|
||||
final TypeInformation<?> type, CouchbasePersistentProperty prop, ConvertingPropertyAccessor accessor) {
|
||||
|
||||
for (Object element : source) {
|
||||
|
||||
@@ -33,6 +33,8 @@ import java.util.regex.Pattern;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseList;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
|
||||
import org.springframework.data.couchbase.core.mapping.Expiration;
|
||||
import org.springframework.data.couchbase.core.query.N1QLExpression;
|
||||
@@ -434,6 +436,12 @@ public class StringBasedN1qlQueryParser {
|
||||
for (Parameter parameter : this.queryMethod.getParameters().getBindableParameters()) {
|
||||
Object rawValue = accessor.getBindableValue(parameter.getIndex());
|
||||
Object value = couchbaseConverter.convertForWriteIfNeeded(rawValue);
|
||||
if (value instanceof CouchbaseDocument) {
|
||||
value = ((CouchbaseDocument) value).export();
|
||||
}
|
||||
if (value instanceof CouchbaseList) {
|
||||
value = ((CouchbaseList) value).export();
|
||||
}
|
||||
putPositionalValue(posValues, value);
|
||||
}
|
||||
return posValues;
|
||||
@@ -452,7 +460,9 @@ public class StringBasedN1qlQueryParser {
|
||||
String placeholder = parameter.getPlaceholder();
|
||||
Object rawValue = accessor.getBindableValue(parameter.getIndex());
|
||||
Object value = couchbaseConverter.convertForWriteIfNeeded(rawValue);
|
||||
|
||||
if (value instanceof CouchbaseDocument) {
|
||||
value = ((CouchbaseDocument) value).export();
|
||||
}
|
||||
if (placeholder != null && placeholder.charAt(0) == ':') {
|
||||
placeholder = placeholder.replaceFirst(":", "");
|
||||
putNamedValue(namedValues, placeholder, value);
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.data.couchbase.domain;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.couchbase.repository.CouchbaseRepository;
|
||||
import org.springframework.data.couchbase.repository.Query;
|
||||
import org.springframework.data.couchbase.repository.ScanConsistency;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@@ -35,4 +36,8 @@ public interface UserSubmissionRepository extends CouchbaseRepository<UserSubmis
|
||||
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
|
||||
List<UserSubmission> findByUsername(String username);
|
||||
|
||||
@Query("UPDATE #{#n1ql.bucket} set address=$2 where meta().id=$1")
|
||||
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
|
||||
List<Airport> setByIdAddress(String id, Address abc);
|
||||
|
||||
}
|
||||
|
||||
@@ -368,14 +368,14 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
AirportRepositoryScanConsistencyTest airportRepositoryRP = (AirportRepositoryScanConsistencyTest) ac
|
||||
.getBean("airportRepositoryScanConsistencyTest");
|
||||
|
||||
List<Airport> sizeBeforeTest = (List<Airport>)airportRepositoryRP.findAll();
|
||||
List<Airport> sizeBeforeTest = (List<Airport>) airportRepositoryRP.findAll();
|
||||
assertEquals(0, sizeBeforeTest.size());
|
||||
|
||||
boolean notFound = false;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Airport vie = new Airport("airports::vie", "vie", "low9");
|
||||
Airport saved = airportRepositoryRP.save(vie);
|
||||
List<Airport> allSaved = (List<Airport>)airportRepositoryRP.findAll();
|
||||
List<Airport> allSaved = (List<Airport>) airportRepositoryRP.findAll();
|
||||
couchbaseTemplate.removeById(Airport.class).one(saved.getId());
|
||||
if (allSaved.isEmpty()) {
|
||||
notFound = true;
|
||||
@@ -542,8 +542,7 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
// set version == 0 so save() will be an upsert, not a replace
|
||||
Airport saved = airportRepository.save(vie.clearVersion());
|
||||
try {
|
||||
airport2 = airportRepository.withOptions(queryOptions().scanConsistency(NOT_BOUNDED))
|
||||
.iata(saved.getIata());
|
||||
airport2 = airportRepository.withOptions(queryOptions().scanConsistency(NOT_BOUNDED)).iata(saved.getIata());
|
||||
if (airport2 == null) {
|
||||
break;
|
||||
}
|
||||
@@ -679,7 +678,7 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
airportRepository.saveAll(
|
||||
Arrays.stream(iatas).map((iata) -> new Airport("airports::" + iata, iata, iata.toLowerCase(Locale.ROOT)))
|
||||
.collect(Collectors.toSet()));
|
||||
couchbaseTemplate.findByQuery(Airport.class).withConsistency(REQUEST_PLUS).all();
|
||||
List<Airport> aList = couchbaseTemplate.findByQuery(Airport.class).withConsistency(REQUEST_PLUS).all();
|
||||
Long count = airportRepository.countFancyExpression(asList("JFK"), asList("jfk"), false);
|
||||
assertEquals(1, count);
|
||||
|
||||
@@ -842,6 +841,24 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateObject() throws Exception {
|
||||
UserSubmission userSubmission = new UserSubmission();
|
||||
userSubmission.setId("123");
|
||||
try {
|
||||
userSubmission.setUsername("updateObject");
|
||||
userSubmissionRepository.save(userSubmission);
|
||||
Address address = new Address(); // plaintext address with encrypted street
|
||||
address.setStreet("Olcott Street");
|
||||
address.setCity("Santa Clara");
|
||||
userSubmissionRepository.setByIdAddress(userSubmission.getId(), address);
|
||||
Optional<UserSubmission> fetched = userSubmissionRepository.findById(userSubmission.getId());
|
||||
assertEquals(address, fetched.get().getAddress());
|
||||
} finally {
|
||||
airportRepository.deleteById(userSubmission.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void stringDeleteTest() throws Exception {
|
||||
Airport airport = new Airport("airports::vie", "vie", "lowx");
|
||||
|
||||
Reference in New Issue
Block a user