Skip to content

Commit 932901e

Browse files
authored
Accept entity parameters to repository methods. (#1595)
Closed #1586.
1 parent 832f314 commit 932901e

File tree

5 files changed

+67
-17
lines changed

5 files changed

+67
-17
lines changed

src/main/java/org/springframework/data/couchbase/core/convert/AbstractCouchbaseConverter.java

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,21 @@
1616

1717
package org.springframework.data.couchbase.core.convert;
1818

19+
import java.util.Collection;
1920
import java.util.Collections;
2021

21-
import com.couchbase.client.java.query.QueryScanConsistency;
2222
import org.springframework.beans.factory.InitializingBean;
2323
import org.springframework.core.convert.ConversionService;
2424
import org.springframework.core.convert.TypeDescriptor;
2525
import org.springframework.core.convert.support.GenericConversionService;
2626
import org.springframework.data.convert.CustomConversions;
2727
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
28+
import org.springframework.data.couchbase.core.mapping.CouchbaseList;
2829
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
2930
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
3031
import org.springframework.data.mapping.model.EntityInstantiators;
32+
import org.springframework.data.util.ClassTypeInformation;
33+
import org.springframework.data.util.TypeInformation;
3134

3235
/**
3336
* An abstract {@link CouchbaseConverter} that provides the basics for the {@link MappingCouchbaseConverter}.
@@ -141,19 +144,34 @@ public Object convertForWriteIfNeeded(CouchbasePersistentProperty prop, Converti
141144
* This convertForWriteIfNeed takes only the value to convert. It cannot access the annotations of the Field being
142145
* converted.
143146
*
144-
* @param value the value to be converted to the class that would actually be stored.
147+
* @param inValue the value to be converted to the class that would actually be stored.
145148
* @return
146149
*/
147150
@Override
148-
public Object convertForWriteIfNeeded(Object value) {
149-
if (value == null) {
151+
public Object convertForWriteIfNeeded(Object inValue) {
152+
if (inValue == null) {
150153
return null;
151154
}
152155

153-
return this.conversions.getCustomWriteTarget(value.getClass()) //
154-
.map(it -> (Object) this.conversionService.convert(value, it)) //
155-
.orElseGet(() -> Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value);
156-
156+
Object value = this.conversions.getCustomWriteTarget(inValue.getClass()) //
157+
.map(it -> (Object) this.conversionService.convert(inValue, it)) //
158+
.orElse(inValue);
159+
160+
Class<?> elementType = value.getClass();
161+
162+
if (elementType == null || conversions.isSimpleType(elementType)) {
163+
value = Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value;
164+
} else if (value instanceof Collection || elementType.isArray()) {
165+
TypeInformation<?> type = ClassTypeInformation.from(value.getClass());
166+
value = ((MappingCouchbaseConverter) this).writeCollectionInternal(MappingCouchbaseConverter.asCollection(value),
167+
new CouchbaseList(conversions.getSimpleTypeHolder()), type, null, null);
168+
} else {
169+
CouchbaseDocument embeddedDoc = new CouchbaseDocument();
170+
TypeInformation<?> type = ClassTypeInformation.from(value.getClass());
171+
((MappingCouchbaseConverter) this).writeInternalRoot(value, embeddedDoc, type, false, null);
172+
value = embeddedDoc;
173+
}
174+
return value;
157175
}
158176

159177
@Override

src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ public MappingCouchbaseConverter(
169169
* @param source the source object.
170170
* @return the target collection.
171171
*/
172-
private static Collection<?> asCollection(final Object source) {
172+
protected static Collection<?> asCollection(final Object source) {
173173
if (source instanceof Collection) {
174174
return (Collection<?>) source;
175175
}
@@ -459,7 +459,7 @@ public void write(final Object source, final CouchbaseDocument target) {
459459
* @param property will be null for the root
460460
*/
461461
@SuppressWarnings("unchecked")
462-
protected void writeInternalRoot(final Object source, CouchbaseDocument target, TypeInformation<?> typeHint,
462+
public void writeInternalRoot(final Object source, CouchbaseDocument target, TypeInformation<?> typeHint,
463463
boolean withId, CouchbasePersistentProperty property) {
464464
if (source == null) {
465465
return;
@@ -759,7 +759,7 @@ private CouchbaseList createCollection(final Collection<?> collection, final Typ
759759
* @param target the target document.
760760
* @return the created couchbase list.
761761
*/
762-
private CouchbaseList writeCollectionInternal(final Collection<?> source, final CouchbaseList target,
762+
public CouchbaseList writeCollectionInternal(final Collection<?> source, final CouchbaseList target,
763763
final TypeInformation<?> type, CouchbasePersistentProperty prop, ConvertingPropertyAccessor accessor) {
764764

765765
for (Object element : source) {

src/main/java/org/springframework/data/couchbase/repository/query/StringBasedN1qlQueryParser.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import org.slf4j.Logger;
3434
import org.slf4j.LoggerFactory;
3535
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
36+
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
37+
import org.springframework.data.couchbase.core.mapping.CouchbaseList;
3638
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
3739
import org.springframework.data.couchbase.core.mapping.Expiration;
3840
import org.springframework.data.couchbase.core.query.N1QLExpression;
@@ -434,6 +436,12 @@ private JsonValue getPositionalPlaceholderValues(ParameterAccessor accessor) {
434436
for (Parameter parameter : this.queryMethod.getParameters().getBindableParameters()) {
435437
Object rawValue = accessor.getBindableValue(parameter.getIndex());
436438
Object value = couchbaseConverter.convertForWriteIfNeeded(rawValue);
439+
if (value instanceof CouchbaseDocument) {
440+
value = ((CouchbaseDocument) value).export();
441+
}
442+
if (value instanceof CouchbaseList) {
443+
value = ((CouchbaseList) value).export();
444+
}
437445
putPositionalValue(posValues, value);
438446
}
439447
return posValues;
@@ -452,7 +460,9 @@ private JsonObject getNamedPlaceholderValues(ParameterAccessor accessor) {
452460
String placeholder = parameter.getPlaceholder();
453461
Object rawValue = accessor.getBindableValue(parameter.getIndex());
454462
Object value = couchbaseConverter.convertForWriteIfNeeded(rawValue);
455-
463+
if (value instanceof CouchbaseDocument) {
464+
value = ((CouchbaseDocument) value).export();
465+
}
456466
if (placeholder != null && placeholder.charAt(0) == ':') {
457467
placeholder = placeholder.replaceFirst(":", "");
458468
putNamedValue(namedValues, placeholder, value);

src/test/java/org/springframework/data/couchbase/domain/UserSubmissionRepository.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.List;
2020

2121
import org.springframework.data.couchbase.repository.CouchbaseRepository;
22+
import org.springframework.data.couchbase.repository.Query;
2223
import org.springframework.data.couchbase.repository.ScanConsistency;
2324
import org.springframework.stereotype.Repository;
2425

@@ -35,4 +36,8 @@ public interface UserSubmissionRepository extends CouchbaseRepository<UserSubmis
3536
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
3637
List<UserSubmission> findByUsername(String username);
3738

39+
@Query("UPDATE #{#n1ql.bucket} set address=$2 where meta().id=$1")
40+
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
41+
List<Airport> setByIdAddress(String id, Address abc);
42+
3843
}

src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -368,14 +368,14 @@ public void saveNotBoundedWithDefaultRepository() {
368368
AirportRepositoryScanConsistencyTest airportRepositoryRP = (AirportRepositoryScanConsistencyTest) ac
369369
.getBean("airportRepositoryScanConsistencyTest");
370370

371-
List<Airport> sizeBeforeTest = (List<Airport>)airportRepositoryRP.findAll();
371+
List<Airport> sizeBeforeTest = (List<Airport>) airportRepositoryRP.findAll();
372372
assertEquals(0, sizeBeforeTest.size());
373373

374374
boolean notFound = false;
375375
for (int i = 0; i < 100; i++) {
376376
Airport vie = new Airport("airports::vie", "vie", "low9");
377377
Airport saved = airportRepositoryRP.save(vie);
378-
List<Airport> allSaved = (List<Airport>)airportRepositoryRP.findAll();
378+
List<Airport> allSaved = (List<Airport>) airportRepositoryRP.findAll();
379379
couchbaseTemplate.removeById(Airport.class).one(saved.getId());
380380
if (allSaved.isEmpty()) {
381381
notFound = true;
@@ -542,8 +542,7 @@ public void saveNotBounded() {
542542
// set version == 0 so save() will be an upsert, not a replace
543543
Airport saved = airportRepository.save(vie.clearVersion());
544544
try {
545-
airport2 = airportRepository.withOptions(queryOptions().scanConsistency(NOT_BOUNDED))
546-
.iata(saved.getIata());
545+
airport2 = airportRepository.withOptions(queryOptions().scanConsistency(NOT_BOUNDED)).iata(saved.getIata());
547546
if (airport2 == null) {
548547
break;
549548
}
@@ -679,7 +678,7 @@ void countSlicePage() {
679678
airportRepository.saveAll(
680679
Arrays.stream(iatas).map((iata) -> new Airport("airports::" + iata, iata, iata.toLowerCase(Locale.ROOT)))
681680
.collect(Collectors.toSet()));
682-
couchbaseTemplate.findByQuery(Airport.class).withConsistency(REQUEST_PLUS).all();
681+
List<Airport> aList = couchbaseTemplate.findByQuery(Airport.class).withConsistency(REQUEST_PLUS).all();
683682
Long count = airportRepository.countFancyExpression(asList("JFK"), asList("jfk"), false);
684683
assertEquals(1, count);
685684

@@ -842,6 +841,24 @@ void stringQueryTest() throws Exception {
842841
}
843842
}
844843

844+
@Test
845+
void updateObject() throws Exception {
846+
UserSubmission userSubmission = new UserSubmission();
847+
userSubmission.setId("123");
848+
try {
849+
userSubmission.setUsername("updateObject");
850+
userSubmissionRepository.save(userSubmission);
851+
Address address = new Address(); // plaintext address with encrypted street
852+
address.setStreet("Olcott Street");
853+
address.setCity("Santa Clara");
854+
userSubmissionRepository.setByIdAddress(userSubmission.getId(), address);
855+
Optional<UserSubmission> fetched = userSubmissionRepository.findById(userSubmission.getId());
856+
assertEquals(address, fetched.get().getAddress());
857+
} finally {
858+
airportRepository.deleteById(userSubmission.getId());
859+
}
860+
}
861+
845862
@Test
846863
void stringDeleteTest() throws Exception {
847864
Airport airport = new Airport("airports::vie", "vie", "lowx");

0 commit comments

Comments
 (0)