diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java index 7824c1320..fbc21dcf3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MappingMongoEntityInformation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 by the original author(s). + * Copyright (c) 2011-2015 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. @@ -17,6 +17,7 @@ package org.springframework.data.mongodb.repository.support; import java.io.Serializable; +import org.bson.types.ObjectId; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; import org.springframework.data.repository.core.support.PersistentEntityInformation; @@ -27,12 +28,14 @@ import org.springframework.data.repository.core.support.PersistentEntityInformat * {@link MongoPersistentEntity} if given. * * @author Oliver Gierke + * @author Christoph Strobl */ public class MappingMongoEntityInformation extends PersistentEntityInformation implements MongoEntityInformation { private final MongoPersistentEntity entityMetadata; private final String customCollectionName; + private final Class fallbackIdType; /** * Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}. @@ -40,7 +43,11 @@ public class MappingMongoEntityInformation extends P * @param entity must not be {@literal null}. */ public MappingMongoEntityInformation(MongoPersistentEntity entity) { - this(entity, null); + this(entity, null, null); + } + + public MappingMongoEntityInformation(MongoPersistentEntity entity, Class fallbackIdType) { + this(entity, (String) null, fallbackIdType); } /** @@ -51,11 +58,16 @@ public class MappingMongoEntityInformation extends P * @param customCollectionName can be {@literal null}. */ public MappingMongoEntityInformation(MongoPersistentEntity entity, String customCollectionName) { + this(entity, customCollectionName, null); + } + + public MappingMongoEntityInformation(MongoPersistentEntity entity, String customCollectionName, Class idType) { super(entity); this.entityMetadata = entity; this.customCollectionName = customCollectionName; + this.fallbackIdType = idType != null ? idType : (Class) ObjectId.class; } /* (non-Javadoc) @@ -71,4 +83,19 @@ public class MappingMongoEntityInformation extends P public String getIdAttribute() { return entityMetadata.getIdProperty().getName(); } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.PersistentEntityInformation#getIdType() + */ + @Override + @SuppressWarnings("unchecked") + public Class getIdType() { + + if (this.entityMetadata.hasIdProperty()) { + return super.getIdType(); + } + + return fallbackIdType != null ? fallbackIdType : (Class) ObjectId.class; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java index 99046df8f..6bf204887 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactory.java @@ -48,6 +48,7 @@ import org.springframework.util.Assert; * * @author Oliver Gierke * @author Thomas Darimont + * @author Christoph Strobl */ public class MongoRepositoryFactory extends RepositoryFactorySupport { @@ -89,7 +90,8 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport { @Override protected Object getTargetRepository(RepositoryInformation information) { - MongoEntityInformation entityInformation = getEntityInformation(information.getDomainType()); + MongoEntityInformation entityInformation = getEntityInformation(information.getDomainType(), + information); return getTargetRepositoryViaReflection(information, entityInformation, mongoOperations); } @@ -106,18 +108,25 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport { * (non-Javadoc) * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getEntityInformation(java.lang.Class) */ - @Override - @SuppressWarnings("unchecked") + // TODO: would be worth discussing if we could alter RepositoryFactorySupport#getEntityInformation to be called with + // RepositoryMetadata instead of the acual domain type class. public MongoEntityInformation getEntityInformation(Class domainClass) { + return getEntityInformation(domainClass, null); + } + + @SuppressWarnings("unchecked") + private MongoEntityInformation getEntityInformation(Class domainClass, + RepositoryInformation information) { MongoPersistentEntity entity = mappingContext.getPersistentEntity(domainClass); if (entity == null) { - throw new MappingException( - String.format("Could not lookup mapping metadata for domain class %s!", domainClass.getName())); + throw new MappingException(String.format("Could not lookup mapping metadata for domain class %s!", + domainClass.getName())); } - return new MappingMongoEntityInformation((MongoPersistentEntity) entity); + return new MappingMongoEntityInformation((MongoPersistentEntity) entity, + information != null ? (Class) information.getIdType() : null); } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java new file mode 100644 index 000000000..e97d0ebdd --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java @@ -0,0 +1,128 @@ +/* + * Copyright 2015 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. + * 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.mongodb.core; + +import static org.hamcrest.core.Is.*; +import static org.junit.Assert.*; +import static org.springframework.data.mongodb.core.query.Criteria.*; +import static org.springframework.data.mongodb.core.query.Query.*; + +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.config.AbstractMongoConfiguration; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.mongodb.Mongo; +import com.mongodb.MongoClient; + +/** + * @author Christoph Strobl + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class NoExplicitIdTests { + + @Configuration + @EnableMongoRepositories(considerNestedRepositories = true) + static class Config extends AbstractMongoConfiguration { + + @Override + protected String getDatabaseName() { + return "test"; + } + + @Override + public Mongo mongo() throws Exception { + return new MongoClient(); + } + } + + @Autowired MongoOperations mongoOps; + @Autowired TypeWithoutExplicitIdPropertyRepository repo; + + @Before + public void setUp() { + mongoOps.dropCollection(TypeWithoutIdProperty.class); + } + + /** + * @see DATAMONGO-1289 + */ + @Test + public void saveAndRetrieveTypeWithoutIdPorpertyViaTemplate() { + + TypeWithoutIdProperty noid = new TypeWithoutIdProperty(); + noid.someString = "o.O"; + + mongoOps.save(noid); + + TypeWithoutIdProperty retrieved = mongoOps.findOne(query(where("someString").is(noid.someString)), + TypeWithoutIdProperty.class); + + assertThat(retrieved.someString, is(noid.someString)); + } + + /** + * @see DATAMONGO-1289 + */ + @Test + public void saveAndRetrieveTypeWithoutIdPorpertyViaRepository() { + + TypeWithoutIdProperty noid = new TypeWithoutIdProperty(); + noid.someString = "o.O"; + + repo.save(noid); + + TypeWithoutIdProperty retrieved = repo.findBySomeString(noid.someString); + assertThat(retrieved.someString, is(noid.someString)); + } + + /** + * @see DATAMONGO-1289 + */ + @Test + public void saveAndRetrieveTypeWithoutIdPorpertyViaRepositoryFindOne() { + + TypeWithoutIdProperty noid = new TypeWithoutIdProperty(); + noid.someString = "o.O"; + + repo.save(noid); + + Map map = mongoOps.findOne(query(where("someString").is(noid.someString)), Map.class, + "typeWithoutIdProperty"); + + TypeWithoutIdProperty retrieved = repo.findOne(map.get("_id").toString()); + assertThat(retrieved.someString, is(noid.someString)); + } + + static class TypeWithoutIdProperty { + + String someString; + } + + static interface TypeWithoutExplicitIdPropertyRepository extends MongoRepository { + + TypeWithoutIdProperty findBySomeString(String someString); + } +}