Skip to content

Commit 0cc050e

Browse files
christophstroblodrotbohm
authored andcommitted
DATAMONGO-1287 - Fix double fetching for lazy DbRefs used in entity constructor.
We now check properties for their usage as constructor arguments, that might already have been resolved, before setting the actual value. This prevents turning already eagerly fetched DBRefs back into LazyLoadingProxies. Original pull request: #335. Related pull request: #322.
1 parent e30eeaa commit 0cc050e

File tree

2 files changed

+86
-3
lines changed

2 files changed

+86
-3
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,8 @@ private <S extends Object> S read(final MongoPersistentEntity<S> entity, final D
264264
accessor.setProperty(idProperty, idValue);
265265
}
266266

267-
final ObjectPath currentPath = path.push(result, entity, idValue != null ? dbo.get(idProperty.getFieldName())
268-
: null);
267+
final ObjectPath currentPath = path.push(result, entity,
268+
idValue != null ? dbo.get(idProperty.getFieldName()) : null);
269269

270270
// Set properties not already set in the constructor
271271
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
@@ -291,7 +291,7 @@ public void doWithAssociation(Association<MongoPersistentProperty> association)
291291
final MongoPersistentProperty property = association.getInverse();
292292
Object value = dbo.get(property.getFieldName());
293293

294-
if (value == null) {
294+
if (value == null || (entity.isConstructorArgument(property) && accessor.getProperty(property) != null)) {
295295
return;
296296
}
297297

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

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3074,6 +3074,75 @@ public void resolvesCyclicDBRefCorrectly() {
30743074
assertThat(contentLoaded.dbrefMessage.id, is(messageLoaded.id));
30753075
}
30763076

3077+
/**
3078+
* @see DATAMONGO-1287
3079+
*/
3080+
@Test
3081+
public void shouldReuseAlreadyResolvedLazyLoadedDBRefWhenUsedAsPersistenceConstrcutorArgument() {
3082+
3083+
Document docInCtor = new Document();
3084+
docInCtor.id = "doc-in-ctor";
3085+
template.save(docInCtor);
3086+
3087+
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
3088+
docInCtor);
3089+
3090+
template.save(source);
3091+
3092+
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
3093+
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
3094+
assertThat(loaded.refToDocUsedInCtor, not(instanceOf(LazyLoadingProxy.class)));
3095+
assertThat(loaded.refToDocNotUsedInCtor, nullValue());
3096+
}
3097+
3098+
/**
3099+
* @see DATAMONGO-1287
3100+
*/
3101+
@Test
3102+
public void shouldNotReuseLazyLoadedDBRefWhenTypeUsedInPersistenceConstrcutorButValueRefersToAnotherProperty() {
3103+
3104+
Document docNotUsedInCtor = new Document();
3105+
docNotUsedInCtor.id = "doc-but-not-used-in-ctor";
3106+
template.save(docNotUsedInCtor);
3107+
3108+
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
3109+
null);
3110+
source.refToDocNotUsedInCtor = docNotUsedInCtor;
3111+
3112+
template.save(source);
3113+
3114+
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
3115+
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
3116+
assertThat(loaded.refToDocNotUsedInCtor, instanceOf(LazyLoadingProxy.class));
3117+
assertThat(loaded.refToDocUsedInCtor, nullValue());
3118+
}
3119+
3120+
/**
3121+
* @see DATAMONGO-1287
3122+
*/
3123+
@Test
3124+
public void shouldRespectParamterValueWhenAttemptingToReuseLazyLoadedDBRefUsedInPersistenceConstrcutor() {
3125+
3126+
Document docInCtor = new Document();
3127+
docInCtor.id = "doc-in-ctor";
3128+
template.save(docInCtor);
3129+
3130+
Document docNotUsedInCtor = new Document();
3131+
docNotUsedInCtor.id = "doc-but-not-used-in-ctor";
3132+
template.save(docNotUsedInCtor);
3133+
3134+
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
3135+
docInCtor);
3136+
source.refToDocNotUsedInCtor = docNotUsedInCtor;
3137+
3138+
template.save(source);
3139+
3140+
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
3141+
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
3142+
assertThat(loaded.refToDocUsedInCtor, not(instanceOf(LazyLoadingProxy.class)));
3143+
assertThat(loaded.refToDocNotUsedInCtor, instanceOf(LazyLoadingProxy.class));
3144+
}
3145+
30773146
static class DoucmentWithNamedIdField {
30783147

30793148
@Id String someIdKey;
@@ -3401,4 +3470,18 @@ static class SomeMessage {
34013470
@org.springframework.data.mongodb.core.mapping.DBRef SomeContent dbrefContent;
34023471
SomeContent normalContent;
34033472
}
3473+
3474+
static class DocumentWithLazyDBrefUsedInPresistenceConstructor {
3475+
3476+
@Id String id;
3477+
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) Document refToDocUsedInCtor;
3478+
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) Document refToDocNotUsedInCtor;
3479+
3480+
@PersistenceConstructor
3481+
public DocumentWithLazyDBrefUsedInPresistenceConstructor(Document refToDocUsedInCtor) {
3482+
this.refToDocUsedInCtor = refToDocUsedInCtor;
3483+
}
3484+
3485+
}
3486+
34043487
}

0 commit comments

Comments
 (0)