From 5d9dbda03b94a0e80843c277098c3ac5cc85bf3a Mon Sep 17 00:00:00 2001 From: Thomas Darimont Date: Fri, 5 Jul 2013 02:24:08 +0200 Subject: [PATCH] DATAMONGO-688 - Improve detection of id properties. Added support for precedence of explicit id property mapping over implicit property mappings. Changed BasicMongoPersistentProperty.getFieldName() to return the mongo _id field name only for the "effective" id property considering the owner entity if already set). Added some test cases for all possible cases to MongoMappingContextUnitTests. Original pull request: #48. --- .../mapping/BasicMongoPersistentEntity.java | 58 ++++++++++ .../mapping/BasicMongoPersistentProperty.java | 24 +++- .../core/mapping/MongoPersistentProperty.java | 13 ++- .../mapping/MongoMappingContextUnitTests.java | 104 +++++++++++++++--- 4 files changed, 180 insertions(+), 19 deletions(-) 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 589e42115..624ed64b5 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 @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.core.mapping; +import java.lang.reflect.Field; import java.util.Comparator; import java.util.HashMap; import java.util.Map; @@ -24,6 +25,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.expression.BeanFactoryAccessor; import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.data.annotation.Id; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.AssociationHandler; import org.springframework.data.mapping.PropertyHandler; @@ -35,6 +37,7 @@ import org.springframework.expression.Expression; import org.springframework.expression.ParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -43,6 +46,7 @@ import org.springframework.util.StringUtils; * * @author Jon Brisbin * @author Oliver Gierke + * @author Thomas Darimont */ public class BasicMongoPersistentEntity extends BasicPersistentEntity implements MongoPersistentEntity, ApplicationContextAware { @@ -136,6 +140,60 @@ public class BasicMongoPersistentEntity extends BasicPersistentEntity implements MongoPersistentProperty { @@ -109,6 +111,15 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope return SUPPORTED_ID_PROPERTY_NAMES.contains(field.getName()); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isExplicitIdProperty() + */ + @Override + public boolean isExplicitIdProperty() { + return isAnnotationPresent(Id.class); + } + /** * Returns the key to be used to store the value of the property inside a Mongo {@link DBObject}. * @@ -117,7 +128,18 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope public String getFieldName() { if (isIdProperty()) { - return ID_FIELD_NAME; + + if (owner == null) { + return ID_FIELD_NAME; + } + + if (owner.getIdProperty() == null) { + return ID_FIELD_NAME; + } + + if (owner.isIdProperty(this)) { + return ID_FIELD_NAME; + } } org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(org.springframework.data.mongodb.core.mapping.Field.class); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java index e76785bc3..6f21cae5d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.springframework.data.mongodb.core.mapping; import org.springframework.core.convert.converter.Converter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; /** @@ -23,6 +25,7 @@ import org.springframework.data.mapping.PersistentProperty; * * @author Oliver Gierke * @author Patryk Wasik + * @author Thomas Darimont */ public interface MongoPersistentProperty extends PersistentProperty { @@ -48,6 +51,14 @@ public interface MongoPersistentProperty extends PersistentProperty pe = context.getPersistentEntity(ClassWithImplicitId.class); - String id; + assertThat(pe, is(not(nullValue()))); + assertThat(pe.isIdProperty(pe.getPersistentProperty("id")), is(true)); + } + + /** + * @see DATAMONGO-688 + */ + @Test + public void mappingContextShouldAcceptClassWithExplicitIdProperty() { + + MongoMappingContext context = new MongoMappingContext(); + BasicMongoPersistentEntity pe = context.getPersistentEntity(ClassWithExplicitId.class); + + assertThat(pe, is(not(nullValue()))); + assertThat(pe.isIdProperty(pe.getPersistentProperty("myId")), is(true)); + } + + /** + * @see DATAMONGO-688 + */ + @Test + public void mappingContextShouldAcceptClassWithExplicitAndImplicitIdPropertyByGivingPrecedenceToExplicitIdProperty() { + + MongoMappingContext context = new MongoMappingContext(); + BasicMongoPersistentEntity pe = context.getPersistentEntity(ClassWithExplicitIdAndImplicitId.class); + assertThat(pe, is(not(nullValue()))); + } + + /** + * @see DATAMONGO-688 + */ + @Test(expected = MappingException.class) + public void rejectsClassWithAmbiguousExplicitIdPropertyFieldMappings() { + + MongoMappingContext context = new MongoMappingContext(); + context.getPersistentEntity(ClassWithMultipleExplicitIds.class); + } + + /** + * @see DATAMONGO-688 + */ + @Test(expected = MappingException.class) + public void rejectsClassWithAmbiguousImplicitIdPropertyFieldMappings() { + + MongoMappingContext context = new MongoMappingContext(); + context.getPersistentEntity(ClassWithMultipleImplicitIds.class); } public class SampleClass { @@ -148,8 +189,7 @@ public class MongoMappingContextUnitTests { class InvalidPerson { - @org.springframework.data.mongodb.core.mapping.Field("foo") - String firstname, lastname; + @org.springframework.data.mongodb.core.mapping.Field("foo") String firstname, lastname; } class Parent { @@ -168,4 +208,34 @@ public class MongoMappingContextUnitTests { return super.getName(); } } + + class ClassWithImplicitId { + + String field; + String id; + } + + class ClassWithExplicitId { + + @Id String myId; + String field; + } + + class ClassWithExplicitIdAndImplicitId { + + @Id String myId; + String id; + } + + class ClassWithMultipleExplicitIds { + + @Id String myId; + @Id String id; + } + + class ClassWithMultipleImplicitIds { + + String _id; + String id; + } }