在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:深度解析与源码剖析》 Spring Data MongoDB 是 Spring 框架中的一个模块,专门用于简化与 MongoDB 数据库的交互。MongoDB 是一个流行的分布式文档数据库,以其灵活性和高性能...
7. **版本控制**:通过`@Version`注解,Spring Data MongoDB可以实现乐观锁机制,确保并发更新的安全性。 8. **索引支持**:你可以声明MongoDB索引,以优化查询性能。Spring Data会自动创建或更新这些索引。 9. **...
Spring Data MongoDB可以通过`@Version`注解实现乐观锁,以处理并发更新。同时,它还支持日志记录和审计功能,确保数据操作的可追溯性。 11. **事件监听**: 通过`MongoEventListener`,可以在文档的生命周期事件...
8. **事件监听**: Spring Data MongoDB支持事件驱动编程,可以监听MongoDB的生命周期事件,如插入、更新、删除等,以执行额外的业务逻辑。 9. **分页和排序**: Repository接口提供了分页和排序的功能,如`Pageable`...
Spring Data Document模块使得与MongoDB的交互变得更为简单,它提供了强大的Repository抽象,允许开发者通过简单的接口定义来执行CRUD操作,无需编写繁琐的DAO层代码。 1. **Repository抽象**: Spring Data ...
以上就是关于"Springboot配置MongoDB连接池源代码"的详细解析,包括了Spring Boot与MongoDB、MyBatis以及MySQL的整合过程。希望对你在开发过程中有所帮助,如果你有任何疑问或需要进一步的信息,请查阅官方文档或...
尽管 Spring Data Commons 是通用的,但与 MongoDB 结合时,它提供了 `MongoTemplate` 和 `MongoRepository`,使得操作 MongoDB 的数据变得更加简单。例如,可以使用 `MongoTemplate` 直接执行 MongoDB 的 CRUD ...
9. **版本控制**:通过`@Version`注解,Spring Data MongoDB可以帮助实现乐观锁,确保并发操作时的数据一致性。 10. **分页和排序**:在Repository接口中,可以使用Pageable对象实现分页查询,并通过`sort()`方法...
#### 三、SpringData方法定义规范 Spring Data JPA 通过定义方法名的约定来推断方法的行为。以下是一些常用的方法名前缀和示例: - **查询所有数据**:`findAll()` 或 `findUsers()`(假设实体类名为 User)。 - *...
综上所述,SpringData通过其强大的抽象层和灵活的方法命名约定,极大地简化了数据库访问逻辑,使得开发者可以专注于业务逻辑的实现,而无需过多关注底层细节。这对于提高开发效率和代码质量有着重要的意义。
总结来说,"JAVA操作MongoDB之spring整合"涉及到的主要知识点包括:Spring Boot项目结构,MongoDB的配置和连接,Spring Data MongoDB的MongoRepository接口,以及如何在Controller层处理HTTP请求。通过这样的整合,...
spring.data.mongodb.uri=mongodb://localhost:27017/your_database_name ``` ### 3. 使用 Morphia 进行实体映射 Morphia 提供了对象到 MongoDB 文档的映射功能。首先,创建一个实体类,例如 `User`: ```java ...
8. **Spring Data**:简化了与各种数据存储的交互,如JPA、MongoDB等,提供了统一的API和方法,减少了与数据层的交互复杂度。 9. **测试支持**:Spring提供了丰富的测试框架,如Spring Test、Spring Boot Test,...
Spring Data MongoDB提供了一套易于使用的API,用于操作MongoDB,而MongoDB Java驱动程序则允许Java应用程序与MongoDB服务器进行通信。 1. **Spring Data MongoDB**:这是Spring Framework的一个子项目,它简化了...
在本项目中,我们将探讨如何将Spring MVC框架与MongoDB数据库进行集成,创建一个实际的应用实例。MongoDB是一个流行的开源、非关系型数据库系统,以其灵活性、可扩展性和高性能著称。而Spring MVC是Java开发Web应用...
**Spring 整合 MongoDB 全解析** MongoDB 是一个高性能、开源、无模式的文档型数据库,被广泛应用于现代Web应用程序开发中。Spring 框架作为Java领域最流行的轻量级框架之一,提供了与多种数据库集成的能力,包括对...
3. **Repository支持**:`weasel-spring-mongodb`可能扩展了Spring Data MongoDB的Repository接口,让你可以定义自己的Repository接口,继承自`MongoRepository`,然后自动实现基本的数据库操作。这样,你可以通过...
Spring Session 提供了一种统一管理和共享 Session 的解决方案,它可以将 Session 数据持久化到多种后端存储,如 Redis、MongoDB 或者 JDBC 数据库,这样即使用户在不同的服务器之间跳转,也能保持会话的一致性。...
在本篇文章中,我们将深入探讨如何使用Spring MVC实现文件的上传与下载,包括注释方式和非注释方式的实现。 首先,我们需要在项目中引入Spring MVC的相关依赖,通常是在pom.xml文件中添加如下Maven依赖: ```xml ...
2. **Spring Data MongoDB**:Spring Data 提供了对 MongoDB 的支持,简化了数据库操作。在项目中引入 Spring Data MongoDB 相关依赖: ```xml <groupId>org.springframework.data <artifactId>spring-data-...