2013-03-07 18 views
2

使用MongoTemplate我試圖存儲一個名爲Person的實體。由於我想使用樂觀鎖定,因此使用@Version註釋對實體進行版本控制。MongoTemplate.save上意外的OptimisticLockingException

當我嘗試使用MongoTemplate.save將新的Person實體存儲到空集合中時,我得到OptimisticLockingException。我沒有想到這一點,因爲我正在創建一個新的對象而不是更新現有的對象。 (並沒有其他線程訪問該集合。)

這是預期的行爲,還是我做錯了什麼?

(如果我使用MongoOperations.insert代替,一切正常。(我想用節省不過,因爲CrudRepository只是一直保存,不會更新。)如果我刪除了@Version註解,它的工作原理也是如此。)

謝謝, 丹尼爾

我的實體類:

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; 
    } 
} 

我的測試設置(這是使用EmbedMongo建立的MongoDB實例):

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. 
    } 
} 

回答

8

當version屬性的類型爲long時,默認值爲0,這似乎是Spring Data MongoDB無法接受的。

將Person類中versionId的類型更改爲Long/Integer。

@Version 
private Long versionId; 
+0

感謝Maciej,這在看完代碼Spring Data MongoDb後證實了我的理解。我的測試還顯示,Long在某些情況下失敗了(現在不記得確切是哪一個),但Integer似乎運行良好。 – Daniel 2013-03-11 16:34:27