Announcement Announcement Module
Collapse
No announcement yet.
MongoDB: Repository delete() not working Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • MongoDB: Repository delete() not working

    I am using spring-data with MongoDB and i have trouble to delete data.

    When i call delete(domainObject) it simply won't delete my data. But deleteAll() works.

    I have written a simple TestCase that shows my problem.

    The Repository:

    Code:
    import org.bson.types.ObjectId;
    import org.springframework.data.document.mongodb.repository.MongoRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface IMyResourceRepository extends MongoRepository<MyResource, ObjectId> {
    
    
    }
    This is my simple DomainObject (shortened):

    Code:
    import org.bson.types.ObjectId;
    
    public class MyResource implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private ObjectId id;
    
        private String mimeType;
    
        private String name;
    
    
        // ...
    
    
    }
    The TestCase

    Code:
        @Test
        public void testInsertAndDelete() {
            MyResource resource = createResource("test.jpg", "image/jpg", "TEST");
    
            // insert
            MyResource saved = resourceRepository.save(resource);
    
            assertNotNull(saved);
    
            // check if insert succeeded
            MyResource found = resourceRepository.findById(saved.getId());
    
            assertNotNull(found);
    
            // check if it is the same
            assertEquals(saved, found);
    
            assertEquals(saved.getId(), found.getId());
    
    
            // delete
            resourceRepository.delete(found);
    
            // check if it isn't available anymore
            MyResource foundAfter = resourceRepository.findById(saved.getId());
    
            assertNull(foundAfter);	// -> fails!!!!!!!
    
            resourceRepository.deleteAll(); // -> works!
        }

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:sec="http://www.springframework.org/schema/security" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
    	xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
    	 http://www.springframework.org/schema/beans/spring-beans.xsd
    	 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    	 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    	 http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
    	 http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
         http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
         http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
    
    	<context:annotation-config />
    
    	<context:component-scan base-package="com....." />
    
    	<mongo:mongo id="mongo" host="localhost" port="27017">
    		<mongo:options connectionsPerHost="10" threadsAllowedToBlockForConnectionMultiplier="5" maxWaitTime="12000" />
    	</mongo:mongo>
    
    	<mongo:repositories base-package="com...." mongo-template-ref="mongoTemplate" />
    
    	<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
    		<constructor-arg name="mongo" ref="mongo" />
    		<constructor-arg name="databaseName" value="wcmpp" />
    		<constructor-arg name="defaultCollectionName" value="..." />
    	</bean>
    
    	<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
    </beans>
    What am i doing wrong, or is this a bug?

    Thanks for your help!

  • #2
    Seems to be a bug… have you tried this with a current snapshot? I think we had some initial bugs and refactorings following those.

    Cheers,
    Ollie

    Comment


    • #3
      It works with the latest SNAPSHOT, thanks a lot.

      Comment


      • #4
        After updating from M1 to the latest snapshot i got a new Problem

        The queries don't work anymore.

        My Resource Class has a list of Tags (tag is a class with a property name and others),
        and queries dont work anymore (i don't get results).

        In the database it looks like this:

        Code:
        {
           "_id": ObjectId("4d95acd99af9d7e9b08d78a9"),
           "tags": {
             "0": {
               "name": "myTestTag"
            }
          },
        Code:
            @Override
            public List<MyResource> findResourcesByTag(String tag) {
                Query query = new Query(Criteria.where("tags.name").is(tag));
                return mongoTemplate.find(query , MyResource.class);
            }
        And "dynamic" queries dont work either:

        Code:
                Query query = new Query();
        
                if (name != null) {
                    query.and(Criteria.where("name").is(name));
                }
        
                if (tag != null) {
                    query.and(Criteria.where("tags.name").is(tag));
                }
        
                if (max != null) {
                    query.limit(max);
                }
        
                if (offset != null) {
                    query.skip(offset);
                }
        
                logger.debug(query.getQueryObject().toString());
        
                List<MyResource> found = mongoTemplate.find(query, MyResource.class);
        It doesn't work name set, or tag or both, or none.

        By the way: what happens if i pass a query with no criteria to find()?

        I expect to get all results, but i get not a single one.

        Comment


        • #5
          i managed to selve the problem, i have to add the collectionName in the find parameter:

          Code:
                  List<MyResource> found = mongoTemplate.find("myResource", query, MyResource.class);
          Otherwise the mongoTemplate uses the default collectionname.

          What i don't understand is that the mongoTemplate even has a default collection.

          Spring-Data is able to store values by using the classname (with the repositories), but i need to specify it when i use the template.

          Do i have to use one mongoTemplate for each collection, or how is it intended to be?

          Why can't the find() method use the Class parameter to guess the collectionName

          Thats kinda like i have to specify the table and the entity in JPA terms.

          Comment


          • #6
            What I'm missing too, is an Annotation or something where i have the possibility to choose the name of the collection in the database.

            i.e.

            Code:
            @CollectionName("notSoStrangeName")
            public class MyStrangeClassName {
            
            }
            then the collection's name is "notSoStrangeName" in the database

            // EDIT:

            found the solution:

            org.springframework.data.document.mongodb.mapping. @Document(collection = "name")

            // Edit2

            ok thats not working :/ at least not with the repositories
            Last edited by Matthias S.; Apr 1st, 2011, 08:07 AM.

            Comment


            • #7
              It seems you're mixing up quite a few things here. MongoTemplate is a rather low level API that does not do any "target collection handling by entity class" as the API clearly indicates. You *can* specify a default collection, but don't have to. If you want to be specific about the collection to persist an entity just use one of the methods MongoTemplate provides that takes the specific collection.

              The repository stuff is pretty much built on top of that. As we have a repository-per-entity model we also apply a "entity-name-to-collection-name" default. This is hidden behind the EntityMetadata/EntityInformation abstraction. So if you configure the MongoRepositoryFactoryBean a MappingContext, the settings you made in the @Document annotation should be regarded. The following namespace snippets should work as well:

              PHP Code:
              <bean id="mongoTemplate" class=".MongoTemplate">
                

                
              <constructor-arg ref="converter" />
                

              </bean>

              <
              mongo:mapping-converter id="converter">

              <
              mongo:repositories base-package="" mongo-template-ref="mongoTemplate" /> 

              Comment


              • #8
                I knew that the Template is more low level and the repositories are build on top. But since i need functionality that is not offered by the repositories (i.e. find with custom query) i have to use it.

                Unfortunately the mongo:mapping-converter does not exist (only mongo:mongo, mongo:repositories and mongo:jmx) in the latest snapshot.

                Comment


                • #9
                  There is: https://github.com/SpringSource/spri...-mongo-1.0.xsd

                  Comment


                  • #10
                    But not here: http://www.springframework.org/schem...-mongo-1.0.xsd

                    Comment


                    • #11
                      Of course, because this is the one of latest milestone release.

                      Comment


                      • #12
                        I switched to the github mongo schema and i currently use spring-data-mongodb-1.0.0.BUILD-20110404.083159-213.jar

                        Can you give me a little example using the xml Konfiguration?

                        My current context.xml is at the bottom, but with this some of my tests fail.

                        I couldn't pass the converter to the mongotemplate as constructor argumennt, but as simple property.

                        I assumed that the base package of converter should be the one of my domain classes,
                        not of the repositories. I couldn't find any Documentation for that.

                        Thank you very much

                        Code:
                        <?xml version="1.0" encoding="UTF-8"?>
                        <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        	xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
                        	xmlns:sec="http://www.springframework.org/schema/security" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
                        	xmlns:mongo="http://www.springframework.org/schema/data/mongo"
                        	xsi:schemaLocation="http://www.springframework.org/schema/beans
                        	 http://www.springframework.org/schema/beans/spring-beans.xsd
                        	 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                        	 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                        	 http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
                        	 http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
                             http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
                             http://www.springframework.org/schema/data/mongo https://github.com/SpringSource/spring-data-document/raw/master/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd">
                        
                        <!-- 
                        http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
                         -->
                        
                        	<context:annotation-config />
                        
                        	<context:component-scan base-package="com...." />
                        
                        	<mongo:mongo id="mongo" host="${mongo.host}" port="27017">
                        		<mongo:options autoConnectRetry="true" connectionsPerHost="10" threadsAllowedToBlockForConnectionMultiplier="5" maxWaitTime="12000" />
                        	</mongo:mongo>
                        
                        	<mongo:repositories base-package="com.....repositories" mongo-template-ref="mongoTemplate" />
                        
                        	<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
                        		<constructor-arg name="mongo" ref="mongo" />
                        		<constructor-arg name="databaseName" value="${mongo.database}" />
                        		<constructor-arg name="defaultCollectionName" value="${mongo.collection}" />
                        		<property name="converter" ref="converter" />
                        	</bean>
                        	
                        	<mongo:mapping-converter 
                        		id="converter" mongo-ref="mongo" 
                        		mongo-template-ref="mongoTemplate" base-package="com.....domain"
                        	/>
                        	
                        	<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
                        
                        </beans>

                        Comment


                        • #13
                          delete() doesn't work again using the repositories in the current snapshot.

                          The object is still in the database and no exception is thrown.

                          if i use mongotemplate

                          Code:
                                  mongoTemplate.findAndRemove("foo", new Query(Criteria.where("id").is(resource.getId())), Foo.class);
                          it works

                          Comment


                          • #14
                            Hi,
                            I realize the thread has been going on a while. We just released M2 and I believe this issue is fixed, if not we'll get on it ASAP.
                            Mark

                            Comment


                            • #15
                              it's fixed

                              Comment

                              Working...
                              X