在model的某个属性上添加@version注解,系统每次保存会自动给该属性值加1,保证数据没有脏写入.但实际使用中,发现使用不当,会导致该检查频繁报错.简单分析@version字段的自增机制.
调用repo*的save方法.最终会调用org.springframework.data.mongodb.repository.support.SimpleMongoRepository类的save方法.
public <S extends T> S save(S entity) { Assert.notNull(entity, "Entity must not be null!"); //isNew方法实现写在下面了. if (entityInformation.isNew(entity)) { /* * insert对version的处理比较简单,直接判定是否存在version注解,存在则设置version对应字段为0 */ mongoOperations.insert(entity, entityInformation.getCollectionName()); } else { mongoOperations.save(entity, entityInformation.getCollectionName()); } return entity; } /** 判断一下主键的值是否存在,存在返回false,反正为true.所以这里的判断是不严谨的,通过前台给设置主键Id的,就会走save,而不是insert了.*/ public boolean isNew(T entity) { ID id = getId(entity); Class<ID> idType = getIdType(); if (!idType.isPrimitive()) { return id == null; } if (id instanceof Number) { return ((Number) id).longValue() == 0L; } throw new IllegalArgumentException(String.format("Unsupported primitive id type %s!", idType)); }
org.springframework.data.mongodb.core.MongoTemplate的save方法会调用doSaveVersioned方法,在该方法中设置version注解对应字段的值.
private <T> void doSaveVersioned(T objectToSave, MongoPersistentEntity<?> entity, String collectionName) { //这个类主要是给model设置值和获取model的值,实现了PersistentPropertyAccessor接口,这个接口在jdk和spring中都有类似的接口,也是一个非常有意思的东西.有兴趣可以具体看看. ConvertingPropertyAccessor convertingAccessor = new ConvertingPropertyAccessor( entity.getPropertyAccessor(objectToSave), mongoConverter.getConversionService()); MongoPersistentProperty idProperty = entity.getIdProperty(); MongoPersistentProperty versionProperty = entity.getVersionProperty(); Object version = convertingAccessor.getProperty(versionProperty); Number versionNumber = convertingAccessor.getProperty(versionProperty, Number.class); // version注解对应的值不存在,转走insert,这里应该是我们出问题的核心所在,因为我们定义的version注解对应的字段是int,都有默认值的.所以只需将之改为Integer,则可以按这里的逻辑判断来处理. // Fresh instance -> initialize version property if (version == null) { doInsert(collectionName, objectToSave, this.mongoConverter); } else { //判断Id字段和值是否存在 assertUpdateableIdIfNotSet(objectToSave); // Create query for entity with the id and old version Object id = convertingAccessor.getProperty(idProperty); Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version)); // Bump version number !!注意,在这里version字段值加1, //后面doUpdate中还有一段判断逻辑:如果要更新的部分字段不包含version对应的字段,而该model有字段使用version注解,则将version的字段=1,并加入更新字段列表中. convertingAccessor.setProperty(versionProperty, versionNumber.longValue() + 1); BasicDBObject dbObject = new BasicDBObject(); maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName)); this.mongoConverter.write(objectToSave, dbObject); maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject, collectionName)); Update update = Update.fromDBObject(dbObject, ID_FIELD); doUpdate(collectionName, query, update, objectToSave.getClass(), false, false); maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject, collectionName)); } }
更改相关字段类型后,测试验证通过.
相关推荐
spring-data-mongodb-1.8.0.RELEASE.jar
Spring集成MongoDB官方指定jar包:spring-data-mongodb-1.4.1.RELEASE.jar
spring-data-mongodb-1.9.1.RELEASE.jar
spring支持mongodb的jar包
spring整合mongodb3.0的jar包,据说已经解决了最新用户验证的问题
注:下文中的 *** 代表文件名中的组件名称。 # 包含: 中文-英文对照文档:【***-javadoc-API文档-中文(简体)-英语-对照版.zip】 jar包下载地址:【***.jar下载地址(官方地址+国内镜像地址).txt】 ...
Spring-data-mongodb_1.9.4_API_docs
spring-data-mongodb-1.0.0.M2.jar ,spring 开源JAR包
springmvc与mongoDB集成需要下面几个的jar包:mongo-java-driver-3.0.1.jarspring-data-commons-1.10.0.RELEASE.jarspring-data-commons-core-1.4.1.RELEASE.jarspring-data-mongodb-1.7.0.RELEASE.jar已经打包在...
Spring-Data-MongoDB 1.9.3、MongoDB3.2整合
java运行依赖jar包
spring-data-mongodb增强工具包,简化 CRUD 操作,提供类mybatis plus的数据库操作。传统关系型数据库及围绕它们构建的orm在项目开发中有很多难用的痛点,而mongodb这种文档性数据库的出现,完美的解决了sql数据库在...
。。。。。。。spring-data-mongodb-1.2.0.RELEASE
spring-data-mongodb-1.8.0.RELEASE(含源码)
spring-data-mongodb1.1.0.jar包
spring-data-mongodb-1.0.0.RC1-javadoc api
spring-data-mongodb-referrence-docs-1.9.4
spring操作mongodb的jdbc工具包,好不容易下载下来的。
spring-data-mongodb-reference 1.5.4
Spring-data-mongodb的文档太少了,基本都是网页版,我把网页做成了chm方便开发人员查看,文档是英文原版,是从官网抓下来的