diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentProperty.java index 251889e66..c42e66bf7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentProperty.java @@ -21,6 +21,8 @@ import java.math.BigInteger; import java.util.HashSet; import java.util.Set; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.bson.types.ObjectId; import org.springframework.data.mapping.AnnotationBasedPersistentProperty; import org.springframework.data.mapping.model.Association; @@ -34,6 +36,8 @@ import com.mongodb.DBObject; */ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty implements MongoPersistentProperty { + + private static final Log LOG = LogFactory.getLog(BasicMongoPersistentProperty.class); private static final Set> SUPPORTED_ID_TYPES = new HashSet>(); private static final Set SUPPORTED_ID_PROPERTY_NAMES = new HashSet(); @@ -56,6 +60,10 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope */ public BasicMongoPersistentProperty(Field field, PropertyDescriptor propertyDescriptor, MongoPersistentEntity owner) { super(field, propertyDescriptor, owner); + + if (isIdProperty() && field.isAnnotationPresent(FieldName.class)) { + LOG.warn(String.format("Invalid usage of %s on id property. Field name will not be considered!", FieldName.class)); + } } /* (non-Javadoc) @@ -87,7 +95,13 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope * @return */ public String getKey() { - return isIdProperty() ? "_id" : getName(); + + if (isIdProperty()) { + return "_id"; + } + + FieldName annotation = getField().getAnnotation(FieldName.class); + return annotation != null ? annotation.value() : getName(); } /* (non-Javadoc) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/FieldName.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/FieldName.java new file mode 100644 index 000000000..fac41437f --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/FieldName.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2011 by the original author(s). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.document.mongodb.mapping; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to allow defining the name of the field a property should use in a Mongo document. This will cause the + * property annotated being persisted to a field with the configured name as wells as being read from it. + * + * @author Oliver Gierke + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD }) +public @interface FieldName { + + String value(); +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentPropertyUnitTests.java new file mode 100644 index 000000000..6a2bbc060 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011 by the original author(s). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.document.mongodb.mapping; + +import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.*; +import java.lang.reflect.Field; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.data.annotation.Id; +import org.springframework.data.util.ClassTypeInformation; +import org.springframework.util.ReflectionUtils; + +/** + * Unit test for {@link BasicMongoPersistentProperty}. + * + * @author Oliver Gierke + */ +public class BasicMongoPersistentPropertyUnitTests { + + MongoPersistentEntity entity; + + @Before + public void setup() { + entity = new BasicMongoPersistentEntity(ClassTypeInformation.from(Person.class)); + } + + @Test + public void usesAnnotatedFieldName() { + + Field field = ReflectionUtils.findField(Person.class, "firstname"); + assertThat(getPropertyFor(field).getKey(), is("foo")); + } + + @Test + public void returns_IdForIdProperty() { + Field field = ReflectionUtils.findField(Person.class, "id"); + MongoPersistentProperty property = getPropertyFor(field); + assertThat(property.isIdProperty(), is(true)); + assertThat(property.getKey(), is("_id")); + } + + @Test + public void returnsPropertyNameForUnannotatedProperties() { + + Field field = ReflectionUtils.findField(Person.class, "lastname"); + assertThat(getPropertyFor(field).getKey(), is("lastname")); + } + + private MongoPersistentProperty getPropertyFor(Field field) { + return new BasicMongoPersistentProperty(field, null, entity); + } + + class Person { + + @Id + String id; + + @FieldName("foo") + String firstname; + String lastname; + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java index c5263bcfd..d9137f0a8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java @@ -190,6 +190,33 @@ public class MappingMongoConverterUnitTests { assertThat(result.sampleEnum, is(SampleEnum.FIRST)); } + /** + * @see DATADOC-144 + */ + @Test + public void considersFieldNameWhenWriting() { + + Person person = new Person(); + person.firstname ="Oliver"; + + DBObject result = new BasicDBObject(); + converter.write(person, result); + + assertThat(result.containsField("foo"), is(true)); + assertThat(result.containsField("firstname"), is(false)); + } + + /** + * @see DATADOC-144 + */ + @Test + public void considersFieldNameWhenReading() { + + DBObject dbObject = new BasicDBObject("foo", "Oliver"); + Person result = converter.read(Person.class, dbObject); + + assertThat(result.firstname, is("Oliver")); + } class ClassWithEnumProperty { @@ -211,6 +238,9 @@ public class MappingMongoConverterUnitTests { public static class Person implements Contact { LocalDate birthDate; + + @FieldName("foo") + String firstname; } static class ClassWithMapProperty {