diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java index 6d814d871..7c56c8c28 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentEntity.java @@ -16,6 +16,7 @@ package org.springframework.data.mongodb.core.mapping; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.Comparator; import java.util.HashMap; import java.util.Map; @@ -305,28 +306,44 @@ public class BasicMongoPersistentEntity extends BasicPersistentEntity { + /* + * (non-Javadoc) + * @see org.springframework.data.mapping.PropertyHandler#doWithPersistentProperty(org.springframework.data.mapping.PersistentProperty) + */ @Override public void doWithPersistentProperty(MongoPersistentProperty persistentProperty) { potentiallyAssertTextScoreType(persistentProperty); potentiallyAssertLanguageType(persistentProperty); + potentiallyAssertDBRefTargetType(persistentProperty); } - private void potentiallyAssertLanguageType(MongoPersistentProperty persistentProperty) { + private static void potentiallyAssertLanguageType(MongoPersistentProperty persistentProperty) { if (persistentProperty.isExplicitLanguageProperty()) { assertPropertyType(persistentProperty, String.class); } } - private void potentiallyAssertTextScoreType(MongoPersistentProperty persistentProperty) { + private static void potentiallyAssertTextScoreType(MongoPersistentProperty persistentProperty) { if (persistentProperty.isTextScoreProperty()) { assertPropertyType(persistentProperty, Float.class, Double.class); } } - private void assertPropertyType(MongoPersistentProperty persistentProperty, Class... validMatches) { + private static void potentiallyAssertDBRefTargetType(MongoPersistentProperty persistentProperty) { + + if (persistentProperty.isDbReference() && persistentProperty.getDBRef().lazy()) { + if (persistentProperty.isArray() || Modifier.isFinal(persistentProperty.getActualType().getModifiers())) { + throw new MappingException(String.format( + "Invalid lazy DBRef property for %s. Found %s which must not be an array nor a final class.", + persistentProperty.getField(), persistentProperty.getActualType())); + } + } + } + + private static void assertPropertyType(MongoPersistentProperty persistentProperty, Class... validMatches) { for (Class potentialMatch : validMatches) { if (ClassUtils.isAssignable(potentialMatch, persistentProperty.getActualType())) { @@ -334,10 +351,9 @@ public class BasicMongoPersistentEntity extends BasicPersistentEntity entity = new BasicMongoPersistentEntity( + ClassTypeInformation.from(AnyDocument.class)); + org.springframework.data.mongodb.core.mapping.DBRef dbRefMock = mock( + org.springframework.data.mongodb.core.mapping.DBRef.class); + when(propertyMock.isDbReference()).thenReturn(true); + when(propertyMock.getDBRef()).thenReturn(dbRefMock); + when(dbRefMock.lazy()).thenReturn(true); + when(propertyMock.getActualType()).thenReturn((Class) Class.class); + entity.addPersistentProperty(propertyMock); + + entity.verify(); + } + + /** + * @see DATAMONGO-1157 + */ + @Test(expected = MappingException.class) + public void verifyShouldThrowErrorForLazyDBRefArray() { + + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + ClassTypeInformation.from(AnyDocument.class)); + org.springframework.data.mongodb.core.mapping.DBRef dbRefMock = mock( + org.springframework.data.mongodb.core.mapping.DBRef.class); + when(propertyMock.isDbReference()).thenReturn(true); + when(propertyMock.getDBRef()).thenReturn(dbRefMock); + when(dbRefMock.lazy()).thenReturn(true); + when(propertyMock.isArray()).thenReturn(true); + entity.addPersistentProperty(propertyMock); + + entity.verify(); + } + + /** + * @see DATAMONGO-1157 + */ + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void verifyShouldPassForLazyDBRefOnNonArrayNonFinalClass() { + + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + ClassTypeInformation.from(AnyDocument.class)); + org.springframework.data.mongodb.core.mapping.DBRef dbRefMock = mock( + org.springframework.data.mongodb.core.mapping.DBRef.class); + when(propertyMock.isDbReference()).thenReturn(true); + when(propertyMock.getDBRef()).thenReturn(dbRefMock); + when(dbRefMock.lazy()).thenReturn(true); + when(propertyMock.getActualType()).thenReturn((Class) Object.class); + entity.addPersistentProperty(propertyMock); + + entity.verify(); + + verify(propertyMock, times(1)).isDbReference(); + } + + /** + * @see DATAMONGO-1157 + */ + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void verifyShouldPassForNonLazyDBRefOnFinalClass() { + + BasicMongoPersistentEntity entity = new BasicMongoPersistentEntity( + ClassTypeInformation.from(AnyDocument.class)); + org.springframework.data.mongodb.core.mapping.DBRef dbRefMock = mock( + org.springframework.data.mongodb.core.mapping.DBRef.class); + when(propertyMock.isDbReference()).thenReturn(true); + when(propertyMock.getDBRef()).thenReturn(dbRefMock); + when(dbRefMock.lazy()).thenReturn(false); + when(propertyMock.getActualType()).thenReturn((Class) Class.class); + entity.addPersistentProperty(propertyMock); + + entity.verify(); + + verify(dbRefMock, times(1)).lazy(); + } + @Document(collection = "contacts") class Contact {