Browse Source

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.7.x
Christoph Strobl 10 years ago committed by Oliver Gierke
parent
commit
0cc050e966
  1. 6
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
  2. 83
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java

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

@ -264,8 +264,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -264,8 +264,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
accessor.setProperty(idProperty, idValue);
}
final ObjectPath currentPath = path.push(result, entity, idValue != null ? dbo.get(idProperty.getFieldName())
: null);
final ObjectPath currentPath = path.push(result, entity,
idValue != null ? dbo.get(idProperty.getFieldName()) : null);
// Set properties not already set in the constructor
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
@ -291,7 +291,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -291,7 +291,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
final MongoPersistentProperty property = association.getInverse();
Object value = dbo.get(property.getFieldName());
if (value == null) {
if (value == null || (entity.isConstructorArgument(property) && accessor.getProperty(property) != null)) {
return;
}

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

@ -3074,6 +3074,75 @@ public class MongoTemplateTests { @@ -3074,6 +3074,75 @@ public class MongoTemplateTests {
assertThat(contentLoaded.dbrefMessage.id, is(messageLoaded.id));
}
/**
* @see DATAMONGO-1287
*/
@Test
public void shouldReuseAlreadyResolvedLazyLoadedDBRefWhenUsedAsPersistenceConstrcutorArgument() {
Document docInCtor = new Document();
docInCtor.id = "doc-in-ctor";
template.save(docInCtor);
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
docInCtor);
template.save(source);
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
assertThat(loaded.refToDocUsedInCtor, not(instanceOf(LazyLoadingProxy.class)));
assertThat(loaded.refToDocNotUsedInCtor, nullValue());
}
/**
* @see DATAMONGO-1287
*/
@Test
public void shouldNotReuseLazyLoadedDBRefWhenTypeUsedInPersistenceConstrcutorButValueRefersToAnotherProperty() {
Document docNotUsedInCtor = new Document();
docNotUsedInCtor.id = "doc-but-not-used-in-ctor";
template.save(docNotUsedInCtor);
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
null);
source.refToDocNotUsedInCtor = docNotUsedInCtor;
template.save(source);
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
assertThat(loaded.refToDocNotUsedInCtor, instanceOf(LazyLoadingProxy.class));
assertThat(loaded.refToDocUsedInCtor, nullValue());
}
/**
* @see DATAMONGO-1287
*/
@Test
public void shouldRespectParamterValueWhenAttemptingToReuseLazyLoadedDBRefUsedInPersistenceConstrcutor() {
Document docInCtor = new Document();
docInCtor.id = "doc-in-ctor";
template.save(docInCtor);
Document docNotUsedInCtor = new Document();
docNotUsedInCtor.id = "doc-but-not-used-in-ctor";
template.save(docNotUsedInCtor);
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
docInCtor);
source.refToDocNotUsedInCtor = docNotUsedInCtor;
template.save(source);
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
assertThat(loaded.refToDocUsedInCtor, not(instanceOf(LazyLoadingProxy.class)));
assertThat(loaded.refToDocNotUsedInCtor, instanceOf(LazyLoadingProxy.class));
}
static class DoucmentWithNamedIdField {
@Id String someIdKey;
@ -3401,4 +3470,18 @@ public class MongoTemplateTests { @@ -3401,4 +3470,18 @@ public class MongoTemplateTests {
@org.springframework.data.mongodb.core.mapping.DBRef SomeContent dbrefContent;
SomeContent normalContent;
}
static class DocumentWithLazyDBrefUsedInPresistenceConstructor {
@Id String id;
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) Document refToDocUsedInCtor;
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) Document refToDocNotUsedInCtor;
@PersistenceConstructor
public DocumentWithLazyDBrefUsedInPresistenceConstructor(Document refToDocUsedInCtor) {
this.refToDocUsedInCtor = refToDocUsedInCtor;
}
}
}

Loading…
Cancel
Save