Skip to content

Commit 4305fbc

Browse files
DATAMONGO-1287 - Fix double fetching for lazy DbRef used in ctor.
We now check properties for their usage as ctor arguments, that might already have been resolved, before setting the actual value. This prevents turning already eagerly fetched DBRefs back into LazyLoadingProxies. Relates to original PR #322.
1 parent ce13395 commit 4305fbc

File tree

2 files changed

+88
-2
lines changed

2 files changed

+88
-2
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,9 @@ public void doWithAssociation(Association<MongoPersistentProperty> association)
290290
final MongoPersistentProperty property = association.getInverse();
291291
Object value = dbo.get(property.getFieldName());
292292

293-
if (value == null) {
293+
if (value == null
294+
|| (entity.getPersistenceConstructor().hasParameters() && entity.isConstructorArgument(property) && accessor
295+
.getProperty(property) != null)) {
294296
return;
295297
}
296298

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

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ protected void cleanDb() {
197197
template.dropCollection(SomeTemplate.class);
198198
template.dropCollection(Address.class);
199199
template.dropCollection(DocumentWithCollectionOfSamples.class);
200+
template.dropCollection(DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
200201
}
201202

202203
@Test
@@ -3035,7 +3036,7 @@ public void takesSortIntoAccountWhenStreaming() {
30353036
*/
30363037
@Test
30373038
public void takesLimitIntoAccountWhenStreaming() {
3038-
3039+
30393040
Person youngestPerson = new Person("John", 20);
30403041
Person oldestPerson = new Person("Jane", 42);
30413042

@@ -3049,6 +3050,75 @@ public void takesLimitIntoAccountWhenStreaming() {
30493050
assertThat(stream.hasNext(), is(false));
30503051
}
30513052

3053+
/**
3054+
* @see DATAMONGO-1287
3055+
*/
3056+
@Test
3057+
public void shouldReuseAlreadyResolvedLazyLoadedDBRefWhenUsedAsPersistenceConstrcutorArgument() {
3058+
3059+
Document docInCtor = new Document();
3060+
docInCtor.id = "doc-in-ctor";
3061+
template.save(docInCtor);
3062+
3063+
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
3064+
docInCtor);
3065+
3066+
template.save(source);
3067+
3068+
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
3069+
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
3070+
assertThat(loaded.refToDocUsedInCtor, not(instanceOf(LazyLoadingProxy.class)));
3071+
assertThat(loaded.refToDocNotUsedInCtor, nullValue());
3072+
}
3073+
3074+
/**
3075+
* @see DATAMONGO-1287
3076+
*/
3077+
@Test
3078+
public void shouldNotReuseLazyLoadedDBRefWhenTypeUsedInPersistenceConstrcutorButValueRefersToAnotherProperty() {
3079+
3080+
Document docNotUsedInCtor = new Document();
3081+
docNotUsedInCtor.id = "doc-but-not-used-in-ctor";
3082+
template.save(docNotUsedInCtor);
3083+
3084+
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
3085+
null);
3086+
source.refToDocNotUsedInCtor = docNotUsedInCtor;
3087+
3088+
template.save(source);
3089+
3090+
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
3091+
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
3092+
assertThat(loaded.refToDocNotUsedInCtor, instanceOf(LazyLoadingProxy.class));
3093+
assertThat(loaded.refToDocUsedInCtor, nullValue());
3094+
}
3095+
3096+
/**
3097+
* @see DATAMONGO-1287
3098+
*/
3099+
@Test
3100+
public void shouldRespectParamterValueWhenAttemptingToReuseLazyLoadedDBRefUsedInPersistenceConstrcutor() {
3101+
3102+
Document docInCtor = new Document();
3103+
docInCtor.id = "doc-in-ctor";
3104+
template.save(docInCtor);
3105+
3106+
Document docNotUsedInCtor = new Document();
3107+
docNotUsedInCtor.id = "doc-but-not-used-in-ctor";
3108+
template.save(docNotUsedInCtor);
3109+
3110+
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
3111+
docInCtor);
3112+
source.refToDocNotUsedInCtor = docNotUsedInCtor;
3113+
3114+
template.save(source);
3115+
3116+
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
3117+
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
3118+
assertThat(loaded.refToDocUsedInCtor, not(instanceOf(LazyLoadingProxy.class)));
3119+
assertThat(loaded.refToDocNotUsedInCtor, instanceOf(LazyLoadingProxy.class));
3120+
}
3121+
30523122
static class DoucmentWithNamedIdField {
30533123

30543124
@Id String someIdKey;
@@ -3375,4 +3445,18 @@ static class SomeMessage {
33753445
@org.springframework.data.mongodb.core.mapping.DBRef SomeContent dbrefContent;
33763446
SomeContent normalContent;
33773447
}
3448+
3449+
static class DocumentWithLazyDBrefUsedInPresistenceConstructor {
3450+
3451+
@Id String id;
3452+
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) Document refToDocUsedInCtor;
3453+
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) Document refToDocNotUsedInCtor;
3454+
3455+
@PersistenceConstructor
3456+
public DocumentWithLazyDBrefUsedInPresistenceConstructor(Document refToDocUsedInCtor) {
3457+
this.refToDocUsedInCtor = refToDocUsedInCtor;
3458+
}
3459+
3460+
}
3461+
33783462
}

0 commit comments

Comments
 (0)