Skip to content

Commit eed9b24

Browse files
christophstroblmp911de
authored andcommitted
Fix id conversion when storing document reference.
This commit makes sure that the string to ObjectId conversion when storing document references follows the general conversion rules. Closes #3847 Original pull request: #3848.
1 parent c350be1 commit eed9b24

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DocumentPointerFactory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.regex.Pattern;
2424

2525
import org.bson.Document;
26+
import org.bson.types.ObjectId;
2627
import org.springframework.core.convert.ConversionService;
2728
import org.springframework.dao.InvalidDataAccessApiUsageException;
2829
import org.springframework.data.annotation.Reference;
@@ -90,6 +91,8 @@ DocumentPointer<?> computePointer(
9091
if (idProperty.hasExplicitWriteTarget()
9192
&& conversionService.canConvert(idValue.getClass(), idProperty.getFieldType())) {
9293
return () -> conversionService.convert(idValue, idProperty.getFieldType());
94+
} else if (idValue instanceof String && ObjectId.isValid((String)idValue)) {
95+
return () -> new ObjectId((String)idValue);
9396
}
9497

9598
return () -> idValue;

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,73 @@ void allowsOneToMayStyleLookupsUsingSelfVariable() {
11801180
assertThat(target.books).containsExactlyInAnyOrder(book1, book3);
11811181
}
11821182

1183+
@Test // GH-3847
1184+
void writeReferenceWithIdStringThatIsAnObjectId() {
1185+
1186+
String rootCollectionName = template.getCollectionName(SingleRefRoot.class);
1187+
1188+
ObjectId id = new ObjectId();
1189+
1190+
SingleRefRoot source = new SingleRefRoot();
1191+
source.id = "root-1";
1192+
source.simpleValueRef = new SimpleObjectRef(id.toHexString(), "me-the-referenced-object");
1193+
1194+
template.save(source);
1195+
1196+
Document target = template.execute(db -> {
1197+
return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first();
1198+
});
1199+
1200+
assertThat(target.get("simpleValueRef")).isEqualTo(id);
1201+
}
1202+
1203+
@Test // GH-3847
1204+
void readWithIdStringThatIsAnObjectId() {
1205+
1206+
ObjectId id = new ObjectId();
1207+
1208+
String rootCollectionName = template.getCollectionName(SingleRefRoot.class);
1209+
String refCollectionName = template.getCollectionName(SimpleObjectRef.class);
1210+
Document refSource = new Document("_id", id).append("value", "me-the-referenced-object");
1211+
Document source = new Document("_id", "id-1").append("value", "v1").append("simpleValueRef", id);
1212+
1213+
template.execute(db -> {
1214+
1215+
db.getCollection(refCollectionName).insertOne(refSource);
1216+
db.getCollection(rootCollectionName).insertOne(source);
1217+
return null;
1218+
});
1219+
1220+
SingleRefRoot result = template.findOne(query(where("id").is("id-1")), SingleRefRoot.class);
1221+
assertThat(result.getSimpleValueRef()).isEqualTo(new SimpleObjectRef(id.toHexString(), "me-the-referenced-object"));
1222+
}
1223+
1224+
@Test // GH-3847
1225+
void readWriteTypeReferenceHavingFixedStringIdTargetType() {
1226+
1227+
ObjectId id = new ObjectId();
1228+
String rootCollectionName = template.getCollectionName(SingleRefRoot.class);
1229+
1230+
ObjectRefHavingStringIdTargetType customStringIdTargetRef = new ObjectRefHavingStringIdTargetType(id.toHexString(),
1231+
"me-the-referenced-object");
1232+
template.save(customStringIdTargetRef);
1233+
1234+
SingleRefRoot source = new SingleRefRoot();
1235+
source.id = "root-1";
1236+
source.customStringIdTargetRef = customStringIdTargetRef;
1237+
template.save(source);
1238+
1239+
Document target = template.execute(db -> {
1240+
return db.getCollection(rootCollectionName).find(Filters.eq("_id", "root-1")).first();
1241+
});
1242+
1243+
assertThat(target.get("customStringIdTargetRef")).isEqualTo(id.toHexString());
1244+
1245+
SingleRefRoot result = template.findOne(query(where("id").is("root-1")), SingleRefRoot.class);
1246+
assertThat(result.getCustomStringIdTargetRef())
1247+
.isEqualTo(new ObjectRefHavingStringIdTargetType(id.toHexString(), "me-the-referenced-object"));
1248+
}
1249+
11831250
@Data
11841251
static class SingleRefRoot {
11851252

@@ -1188,7 +1255,7 @@ static class SingleRefRoot {
11881255

11891256
@DocumentReference SimpleObjectRefWithReadingConverter withReadingConverter;
11901257

1191-
@DocumentReference(lookup = "{ '_id' : '?#{#target}' }") //
1258+
@DocumentReference(lookup = "{ '_id' : ?#{#target} }") //
11921259
SimpleObjectRef simpleValueRef;
11931260

11941261
@DocumentReference(lookup = "{ '_id' : '?#{#target}' }", lazy = true) //
@@ -1211,6 +1278,8 @@ static class SingleRefRoot {
12111278
ObjectRefOnNonIdField lazyObjectValueRefOnNonIdFields;
12121279

12131280
@DocumentReference ObjectRefHavingCustomizedIdTargetType customIdTargetRef;
1281+
1282+
@DocumentReference ObjectRefHavingStringIdTargetType customStringIdTargetRef;
12141283
}
12151284

12161285
@Data
@@ -1325,6 +1394,14 @@ static class ObjectRefHavingCustomizedIdTargetType {
13251394
String name;
13261395
}
13271396

1397+
@Data
1398+
@AllArgsConstructor
1399+
static class ObjectRefHavingStringIdTargetType {
1400+
1401+
@MongoId(targetType = FieldType.STRING) String id;
1402+
String name;
1403+
}
1404+
13281405
static class ReferencableConverter implements Converter<ReferenceAble, DocumentPointer<Object>> {
13291406

13301407
@Nullable

0 commit comments

Comments
 (0)