Announcement Announcement Module
Collapse
No announcement yet.
Unexpected OptimisticLockingException on MongoTemplate.save Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Unexpected OptimisticLockingException on MongoTemplate.save

    Hello,
    Any suggestions regarding the following problem would be much appreciated.

    Using MongoTemplate I'm trying to store an entity called Person. Since I want to use optimistic locking, the entity is versioned using the @Version annotation.

    When I try to store a new Person entity into an empty collection using MongoTemplate.save, I get OptimisticLockingException. I didn't expect this, since I'm creating a new object rather than updating an existing one. (And no other thread is accessing the collection.)

    Is this expected behavior, or am I doing something wrong?

    (If I use MongoOperations.insert instead, everything works. (I want to use save though, since CrudRepository only has save, not update.) If I remove the @Version annotation, it works as well.)

    I'm using version 1.2.0.RELEASE of spring-data-mongodb.

    Thanks,
    Daniel


    My entity class:

    Code:
    import org.bson.types.ObjectId;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.annotation.Version;
    import org.springframework.data.mongodb.core.mapping.Document;
    
    @Document
    public class Person {
    
        @Version
        private long versionId;
    
        @Id
        private ObjectId id;
    
        private final String name;
    
        public Person(String name) {
            this.name = name;
        }
    
        public long getVersionId() {
            return versionId;
        }
    
        public ObjectId getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            Person person = (Person) o;
    
            if (id != null ? !id.equals(person.id) : person.id != null) return false;
    
            return true;
        }
    
        @Override
        public int hashCode() {
            return id != null ? id.hashCode() : 0;
        }
    }
    My test setup (which is using EmbedMongo to set up a MongoDb instance):

    Code:
    import com.mongodb.Mongo;
    import de.flapdoodle.embed.mongo.MongodExecutable;
    import de.flapdoodle.embed.mongo.MongodProcess;
    import de.flapdoodle.embed.mongo.MongodStarter;
    import de.flapdoodle.embed.mongo.config.MongodConfig;
    import de.flapdoodle.embed.mongo.distribution.Version;
    import de.flapdoodle.embed.process.runtime.Network;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.data.mapping.context.MappingContext;
    import org.springframework.data.mongodb.MongoDbFactory;
    import org.springframework.data.mongodb.core.MongoOperations;
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
    import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
    import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
    
    public class MongoDbTest {
    
        private MongodExecutable mongodExe;
        private MongodProcess mongod;
        private Mongo mongo;
        private MongoOperations mongoOperations;
    
        @Before
        public void setUp() throws Exception {
            MongodStarter runtime = MongodStarter.getDefaultInstance();
    
            mongodExe = runtime.prepare(new MongodConfig(Version.Main.V2_0, 12345, Network.localhostIsIPv6()));
            mongod = mongodExe.start();
            mongo = new Mongo("localhost", 12345);
    
            MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongo, "database");
    
            MappingContext mappingContext = new MongoMappingContext();
            MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(mongoDbFactory, mappingContext);
    
            mongoOperations = new MongoTemplate(mongoDbFactory, mappingMongoConverter);
        }
    
        @After
        public void tearDown() {
           mongod.stop();
           mongodExe.stop();
        }
    
        @Test
        public void testSave() {
            Person person = new Person("Joe");
            mongoOperations.save(person);  // This call throws OptimisticLockingException.
        }
    }
    Last edited by daniel.s; Mar 8th, 2013, 03:57 AM. Reason: Added version information

  • #2
    Found a solution

    It seems I must use a non-primitive for the @Version field:

    Code:
    @Version
    private Integer versionId;
    With the above change, I no longer get the unexpected exception. It also works fine for actually getting the OptimisticLockingException when I'm expecting it.

    Not sure why this is the case, any ideas?

    Comment


    • #3
      Would you mind creating a ticket for that scenario?

      Comment

      Working...
      X