`
sanyecao2314
  • 浏览: 134734 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

spring-data-mongodb的@version注解的后台实现逻辑简单解析.

阅读更多

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

 

更改相关字段类型后,测试验证通过.

0
0
分享到:
评论

相关推荐

    spring-data-mongodb-1.8.0.RELEASE(含源码)

    《Spring Data MongoDB 1.8.0.RELEASE:深度解析与源码剖析》 Spring Data MongoDB 是 Spring 框架中的一个模块,专门用于简化与 MongoDB 数据库的交互。MongoDB 是一个流行的分布式文档数据库,以其灵活性和高性能...

    spring-data-mongodb1.2.0

    7. **版本控制**:通过`@Version`注解,Spring Data MongoDB可以实现乐观锁机制,确保并发更新的安全性。 8. **索引支持**:你可以声明MongoDB索引,以优化查询性能。Spring Data会自动创建或更新这些索引。 9. **...

    spring-data-mongodb api

    Spring Data MongoDB可以通过`@Version`注解实现乐观锁,以处理并发更新。同时,它还支持日志记录和审计功能,确保数据操作的可追溯性。 11. **事件监听**: 通过`MongoEventListener`,可以在文档的生命周期事件...

    Spring-data + MongoDb源码

    8. **事件监听**: Spring Data MongoDB支持事件驱动编程,可以监听MongoDB的生命周期事件,如插入、更新、删除等,以执行额外的业务逻辑。 9. **分页和排序**: Repository接口提供了分页和排序的功能,如`Pageable`...

    spring-data-document-1.0.0.M4

    Spring Data Document模块使得与MongoDB的交互变得更为简单,它提供了强大的Repository抽象,允许开发者通过简单的接口定义来执行CRUD操作,无需编写繁琐的DAO层代码。 1. **Repository抽象**: Spring Data ...

    Springboot配置MongoDB连接池源代码

    以上就是关于"Springboot配置MongoDB连接池源代码"的详细解析,包括了Spring Boot与MongoDB、MyBatis以及MySQL的整合过程。希望对你在开发过程中有所帮助,如果你有任何疑问或需要进一步的信息,请查阅官方文档或...

    spring-data-commons1.50

    尽管 Spring Data Commons 是通用的,但与 MongoDB 结合时,它提供了 `MongoTemplate` 和 `MongoRepository`,使得操作 MongoDB 的数据变得更加简单。例如,可以使用 `MongoTemplate` 直接执行 MongoDB 的 CRUD ...

    最新spring-data-mongo官方示例

    9. **版本控制**:通过`@Version`注解,Spring Data MongoDB可以帮助实现乐观锁,确保并发操作时的数据一致性。 10. **分页和排序**:在Repository接口中,可以使用Pageable对象实现分页查询,并通过`sort()`方法...

    Spring-data-jpa 学习笔记.docx

    #### 三、SpringData方法定义规范 Spring Data JPA 通过定义方法名的约定来推断方法的行为。以下是一些常用的方法名前缀和示例: - **查询所有数据**:`findAll()` 或 `findUsers()`(假设实体类名为 User)。 - *...

    spring-data的学习笔记

    综上所述,SpringData通过其强大的抽象层和灵活的方法命名约定,极大地简化了数据库访问逻辑,使得开发者可以专注于业务逻辑的实现,而无需过多关注底层细节。这对于提高开发效率和代码质量有着重要的意义。

    JAVA操作MongoDB之spring整合

    总结来说,"JAVA操作MongoDB之spring整合"涉及到的主要知识点包括:Spring Boot项目结构,MongoDB的配置和连接,Spring Data MongoDB的MongoRepository接口,以及如何在Controller层处理HTTP请求。通过这样的整合,...

    spring集成mongodb

    spring.data.mongodb.uri=mongodb://localhost:27017/your_database_name ``` ### 3. 使用 Morphia 进行实体映射 Morphia 提供了对象到 MongoDB 文档的映射功能。首先,创建一个实体类,例如 `User`: ```java ...

    spring-framework-nogit.7z

    8. **Spring Data**:简化了与各种数据存储的交互,如JPA、MongoDB等,提供了统一的API和方法,减少了与数据层的交互复杂度。 9. **测试支持**:Spring提供了丰富的测试框架,如Spring Test、Spring Boot Test,...

    spring集成mongo所需jar

    Spring Data MongoDB提供了一套易于使用的API,用于操作MongoDB,而MongoDB Java驱动程序则允许Java应用程序与MongoDB服务器进行通信。 1. **Spring Data MongoDB**:这是Spring Framework的一个子项目,它简化了...

    spring mvc 集成mongoDB项目 例子

    在本项目中,我们将探讨如何将Spring MVC框架与MongoDB数据库进行集成,创建一个实际的应用实例。MongoDB是一个流行的开源、非关系型数据库系统,以其灵活性、可扩展性和高性能著称。而Spring MVC是Java开发Web应用...

    Spring整合mongodb详解

    **Spring 整合 MongoDB 全解析** MongoDB 是一个高性能、开源、无模式的文档型数据库,被广泛应用于现代Web应用程序开发中。Spring 框架作为Java领域最流行的轻量级框架之一,提供了与多种数据库集成的能力,包括对...

    weasel-spring-mongodb:一个封装了对mongodb的包,基于spring

    3. **Repository支持**:`weasel-spring-mongodb`可能扩展了Spring Data MongoDB的Repository接口,让你可以定义自己的Repository接口,继承自`MongoRepository`,然后自动实现基本的数据库操作。这样,你可以通过...

    spring-session例子工程

    Spring Session 提供了一种统一管理和共享 Session 的解决方案,它可以将 Session 数据持久化到多种后端存储,如 Redis、MongoDB 或者 JDBC 数据库,这样即使用户在不同的服务器之间跳转,也能保持会话的一致性。...

    Spring MVC upload/download file(注释和非注释实现)

    在本篇文章中,我们将深入探讨如何使用Spring MVC实现文件的上传与下载,包括注释方式和非注释方式的实现。 首先,我们需要在项目中引入Spring MVC的相关依赖,通常是在pom.xml文件中添加如下Maven依赖: ```xml ...

    springMVC整合MongoDb整个工程下载

    2. **Spring Data MongoDB**:Spring Data 提供了对 MongoDB 的支持,简化了数据库操作。在项目中引入 Spring Data MongoDB 相关依赖: ```xml &lt;groupId&gt;org.springframework.data &lt;artifactId&gt;spring-data-...

Global site tag (gtag.js) - Google Analytics