`
worldly
  • 浏览: 43732 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

浅谈spring模板化处理风格操纵mongodb的使用

阅读更多

在spring已经成为Java web开发者必学技能的今天,适应spring编程风格将有助于快速理解和学习spring相关项目,避开aop和ioc不谈,比如工厂方法模式的身影随处可见,今天讨论的是spring 访问mongo的API模板,这种模板化的处理方式,也是spring常见的,以下是几个例子:

1.spring-ldap-core中的ldapTemplate

2.spring-jdbc中的jdbcTemplate

3.mybatis-spring中的sqlSessionTemplate

4.spring-data-mongodb中的MongoTemplate

,等等吧,最近在做关于mongo的项目,所以讲讲MongoTemplate,本文的代码是基于

spring-data-commons-1.10.0.RELEASE.jar

spring-data-mongodb-1.7.0.RELEASE.jar

mongo-java-driver-3.2.2.jar

当然还会有spring环境的包,这不是本文的重点,所以忽略。

一、查看源码了解MongoTemplate

继续查看MongoOperations和ApplicationContextAware发现,MongoTemplate中的所有对mongo数据操纵的方法都是来自于接口MongoOperations:



 至此,我们基本了解了MongoTemplate,我们已经迫切需要使用它了,那我们必须实例化它,所以有必要认识一下它的构造子:



 可以看到,有四个构造函数可用,前俩个源码如下

 

public MongoTemplate(Mongo mongo, String databaseName) {
		this(new SimpleMongoDbFactory(mongo, databaseName), null);
	}
public MongoTemplate(Mongo mongo, String databaseName, UserCredentials userCredentials) {
		this(new SimpleMongoDbFactory(mongo, databaseName, userCredentials));
	}
 但是SimpleMongoDbFactory(mongo, databaseName)已经是被标记为废弃的方法,所以不能用它们去实例化MongoTemplate,再看剩下两个构造子的源码:
public MongoTemplate(MongoDbFactory mongoDbFactory) {
		this(mongoDbFactory, null);
	}
public MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) {

		Assert.notNull(mongoDbFactory);

		this.mongoDbFactory = mongoDbFactory;
		this.exceptionTranslator = mongoDbFactory.getExceptionTranslator();
		this.mongoConverter = mongoConverter == null ? getDefaultMongoConverter(mongoDbFactory) : mongoConverter;
		this.queryMapper = new QueryMapper(this.mongoConverter);
		this.updateMapper = new UpdateMapper(this.mongoConverter);

		// We always have a mapping context in the converter, whether it's a simple one or not
		mappingContext = this.mongoConverter.getMappingContext();
		// We create indexes based on mapping events
		if (null != mappingContext && mappingContext instanceof MongoMappingContext) {
			indexCreator = new MongoPersistentEntityIndexCreator((MongoMappingContext) mappingContext, mongoDbFactory);
			eventPublisher = new MongoMappingEventPublisher(indexCreator);
			if (mappingContext instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher);
			}
		}
	}
 通过上述源码可以清晰的看到这两个方法有个共同参数MongoDbFactory,第二个参数MongoConverter作用是:“Central Mongo specific converter interface which combines {@link MongoWriter} and {@link MongoReader}”(源码注释),所以我们决定使用第三个构造子,即通过MongoDbFactory对象生MongoTemplate实例,那又需要我们查看MongoDbFactory的构造子,最终我们可以通过host,port,username,password,dbname构造一个mongo实例,从而通过该实例构造一个MongoDbFactory对象,最终可以使用其成功实例化MongoTemplate,以下是在spring配置文件中的配置:
<!-- 加载mongodb的属性配置文件 -->
	<context:property-placeholder location="classpath:/mongo/mongodb.properties" />
	<!-- 构造MongoDbFactory对象 -->
	<mongo:db-factory id="mongoDbFactory" host="${mongo.host}"
		port="${mongo.port}" dbname="${mongo.dbname}" username="${mongo.username}"
		password="${mongo.password}" />
	<!-- 构造MongoTemplate -->
	<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
		<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
	</bean>
 这样,我们需要的MongoTemplate实例会随着spring容器的启动而生成。下面我们要讨论的是基于该实例进行mongo的数据操纵(MongoDB的安装等环境准备工作省略)。
二、基于MongoTemplate对象的数据操纵
前面已经讨论过,基于MongoTemplate的数据从操纵实际上是接口MongoOperations中方法的实现和重载。本文只讨论CRUD四中常见操作:
1.查询
mongo中支持对数据的排序和分页,如下是笔者对分页查询的实现:
/**
	 * 查询分页数据
	 * @author young
	 * @param QueryEntity
	 *            查询条件分装实体
	 * @param entityClass
	 *            确定集合名称的实体类
	 */
	public <T> List<T> queryPageData(QueryEntity queryEntity, Class<T> entityClass) {
		Assert.notNull(entityClass, "entityClass must not be null");
		if (!hasCollection(entityClass)) {
			logger.info("collection  determied by entityClass not be found ");
			return null;
		}
		Query query = QueryEntityConverter.getQueryStataments(queryEntity);
		List<T> listResult = getMongoTemplate().find(query, entityClass);
		return listResult;
	}

	/**
	 * 查询分页数据
	 * @author young
	 * @param queryEntity
	 *            查询条件分装实体
	 * @param collectionName
	 *            集合名称
	 * @return
	 */
	public List<? extends Object> queryPageData(QueryEntity queryEntity, String collectionName) {
		Assert.notNull(collectionName, "collection name must not null");
		if (!hasCollection(collectionName)) {
			logger.info("collection named " + collectionName + " not be found");
			return null;
		}
		Query query = QueryEntityConverter.getQueryStataments(queryEntity);
		List<? extends Object> listResult = getMongoTemplate().find(query, Object.class, collectionName);
		return listResult;

	}
 其中,QueryEntity是对分页排序参数的封装,通过它转换成查询对象Query,而entityClass的作用在于确定mongodb中的collection name,即集合名称,还有一个作用就是对query结果集的映射。在第二个方法中我们指定了collection name,用Object对象完成结果集映射。从而同样可以实现功能,而又拜托了实体绑定带来的繁琐。
2.插入
我们知道,mongodb是以一种类似于json的bson格式存放数据到文件中的,它的插入就是基于内存的文件读写操作。所以对数据的插入操作限制很宽泛,几乎任何形式的数据,只要能装换成json的数据或者json字符创的形式数据都可以直接插入,笔者也最喜欢这种简单有用的操作,是nosql基于文件的数据读写而不是结构化数据库技术执行SQL语句来实现数据的读写,在这点上,MongoDB可以对SQL注入攻击天然不感冒。下面是笔者实现的代码:
/**
	 * 批量插入
	 * @author young
	 * @param json
	 *            需要插入的json串文档
	 * @param collectionName
	 *            集合名称
	 */
	public void insertMany(Object json, String collectionName) {
		Assert.notNull(json, "you can not save a null object into a collection");
		Assert.notNull(collectionName, "collection name must be determined by parameter collectionName");
		if (!hasCollection(collectionName)) {
			logger.info("collection named " + collectionName + " not be found b");
		}
		getMongoTemplate().insert(json, collectionName);

	}

	/**
	 * 批量插入
	 * @author young
	 * @param batchToSave
	 *            插入文档列表
	 * @param collectionName
	 *            集合名称
	 */
	public <T> void insertMany(List<T> batchToSave, String collectionName) {
		Assert.notNull(batchToSave, "you can not save a null object into a collection");
		Assert.notNull(collectionName, "collection name must be determined by parameter collectionName");
		if (!hasCollection(collectionName)) {
			logger.info("collection named " + collectionName + " not be found ");
		}
		getMongoTemplate().insert(batchToSave, collectionName);
	}

	/**
	 * 批量插入
	 * @author young
	 * @param batchToSave
	 *            插入文档列表
	 * @param entityClass
	 *            确定集合名称的实体类
	 */
	public <T> void insertMany(List<T> batchToSave, Class<T> entityClass) {
		Assert.notNull(batchToSave, "you can not save a null object into a collection");
		Assert.notNull(entityClass, "entityClass must not be null");
		if (!hasCollection(entityClass)) {
			logger.info("collection  determied by entityClass not be found ");
			return;
		}
		getMongoTemplate().insert(batchToSave, entityClass);
	}
 3.更新
更新同插入、删除一样也是一种写操作。一般而言,对于数据库操作,性能瓶颈往往是是插入和查询,尤其是查询,尽管如此,更新数据也是必不可少的。MongoDB提供了丰富的更新操作,如更新某些字段的值的set操作符、给指定键的值增加值的inc操作符、修改某些collection的键值的rename操作符、删除集合中的某些键的unset操作符、给指定的键追加值的pull操作符、给某个数组键增加值的addToSet操作符、删除基于方向的第一个或者最后一个键的pop操作。如下是笔者实现的对指定键的值进行的批量更新操作:
/**
	 * @author young
	 * @param queryEntity
	 *            查询条件分装实体
	 * @param updateEntity
	 *            更新实体
	 * @param collectionName
	 *            集合名称
	 * @return
	 */
public int updateMany(QueryEntity queryEntity, Map<String, Object> updateEntity, String collectionName) {
		Assert.notNull(collectionName, "collection name must not be null ");
		if (!hasCollection(collectionName)) {
			logger.info("collection named " + collectionName + " not be found ");
			return -1;
		}
		Query query = QueryEntityConverter.getQueryStataments(queryEntity);
		Update update = UpdateEntityConverter.getKeysUpdateStatment(updateEntity);
		return getMongoTemplate().updateMulti(query, update, collectionName).getN();
	}

	/**
	 * @author young
	 * @param queryEntity
	 *            查询条件分装实体
	 * @param updateEntity
	 *            更新实体
	 * @param entityClass
	 *            确定集合名称的实体类
	 * @return
	 */
	public <T> int updateMany(QueryEntity queryEntity, Map<String, Object> updateEntity, Class<T> entityClass) {
		Assert.notNull(entityClass, "entityClass must not be null");
		if (!hasCollection(entityClass)) {
			logger.info("collection  determied by entityClass not be found ");
			return -1;
		}
		Query query = QueryEntityConverter.getQueryStataments(queryEntity);
		Update update = UpdateEntityConverter.getKeysUpdateStatment(updateEntity);
		return getMongoTemplate().updateMulti(query, update, entityClass).getN();
	}
 4.删除
删除操作对于一个开发人员而言是必须谨慎的操作,以至于好些公司的所谓删除操作是假删除,防止操作失误带来的损失。MongoDB数据库的删除操作也是很谨慎的,如在MongoDB中插入数据,只需满足格式要求,可以反复插入除主键字段外其他部分都相同的数据;但是对于删除,MongoDB的态度就是“在某些模糊描述的情况下,宁可不删”。这本身就是MongoDB的一种特性。其实,任何数据库的删除操作,都可以分为查询和删除两部分,前者是为了标记需要删除的数据,后者才是对标记数据的清理操作,所以笔者以为,删除操作的性能很大程度上是依赖于查询,它们都依赖于数据组织方式,如索引的建立,当然了更新操作也一样。如下是笔者对删除的实现:
/**
	 * 删除指定集合中的指定文档
	 * @author young
	 * @param collectionName
	 *            集合名称
	 * @param queryEntity
	 *            查询条件封装实体类,确定了需要删除的文档
	 * @return
	 */
	public int removeMany(QueryEntity queryEntity, String collectionName) {
		Assert.notNull(collectionName, "collection name must not be null ");
		if (!hasCollection(collectionName)) {
			logger.info("collection named " + collectionName + " not be found ");
			return -1;
		}
		Query query = QueryEntityConverter.getQueryStataments(queryEntity);
		return getMongoTemplate().remove(query, collectionName).getN();
	}

	/**
	 * 删除指定集合中的指定文档
	 * @author 
	 * @param queryEntity
	 *            查询条件封装实体类,确定了需要删除的文档
	 * @param entityClass
	 *            确定集合名称的实体类
	 * @return
	 */
	public <T> int removeMany(QueryEntity queryEntity, Class<T> entityClass) {
		Assert.notNull(entityClass, "entityClass must not be null");
		if (!hasCollection(entityClass)) {
			logger.info("collection  determied by entityClass not be found ");
			return -1;
		}
		Query query = QueryEntityConverter.getQueryStataments(queryEntity);
		return getMongoTemplate().remove(query, entityClass).getN();
	}
 到现在为止,我们已经完成了对MongoDB中数据库的增删查改等基本操作,但是一款优秀的产品,高级特性才是闪光的地方。MongoDB而言,数据读写的高性能,在背后支持的是基于内存操作,以及丰富的索引支持,淡然了查询优化器的作用不可小觑,在这点上索引和数据归类划分是我们开发人员讨论的重点,既要保证数据划分有利于业务逻辑,又要保证读写性能;在本文的最后,需要指出的是MongoDB作为一种nosql数据库,也支持丰富的数据聚合和map-reduce操作,这也是笔者最有兴趣的地方,不过鉴于性能和数据库io负荷的考虑,后台执行应该是一种经过实践检验的不错方式。
 

 

 

 

 

 

 

 

 


  • 大小: 20.9 KB
  • 大小: 319.3 KB
  • 大小: 107.8 KB
分享到:
评论

相关推荐

    Spring Data MongoDB API(Spring Data MongoDB 开发文档).CHM

    Spring Data MongoDB API。 Spring Data MongoDB 开发文档。

    spring mvc+spring data+mongodb实例1

    在本实例中,我们将探讨如何使用Spring MVC、Spring Data以及MongoDB来构建一个实际的应用程序。Spring MVC是Spring框架的一部分,用于构建Web应用程序,而Spring Data则是Spring项目下的一个模块,它简化了与各种...

    Spring-Data-MongoDB3.2

    **Spring Data MongoDB 3.2 整合指南** 在当今的软件开发中,Spring框架以其强大的功能和灵活性深受开发者喜爱,而MongoDB作为一款非关系型数据库,因其高性能、高可扩展性和灵活的数据模型,成为了大数据和实时...

    Spring Data MongoDB中文文档

    - **Spring Data MongoDB** 支持 MongoDB 的聚合框架,可以使用 `Aggregation` 和 `AggregationOperation` 来构建复杂的聚合管道。 - 聚合框架支持多种操作,包括但不限于 `$match`, `$group`, `$sort`, `$project` ...

    spring-data使用mongodbTemplate对MongoDB进行读写操作

    在`App.java`中,你可以看到如何初始化和使用`MongoDBTemplate`。通常,你需要通过`ApplicationContext`获取`MongoDbFactory`,然后使用这个工厂创建`MongoDBTemplate`实例。 ```java ApplicationContext context =...

    SpringMongodb参考文档.docx

    1.了解Spring 2.了解NoSQL和文档数据库 3.要求 4.其他帮助资源 4.1。支持 4.1.1。社区论坛 4.1.2。专业支持 4.2。发展之后 5.新&值得注意的 5.1。Spring Data MongoDB 2.1中的新特性 5.2。Spring Data MongoDB 2.0...

    spring mongodb 中文文档

    Spring Data MongoDB 使用`MongoConverter` 和`MongoMappingContext` 来处理对象到MongoDB 文档的转换。 12. **分页与排序** Repository 接口中的`Pageable` 参数可用于实现分页查询,`Sort` 参数则用于指定排序...

    Spring+SpringMVC+MongoDB应用

    标题中的“Spring+SpringMVC+MongoDB应用”是指一个集成使用了Spring框架、SpringMVC模块以及MongoDB数据库的项目。这个项目旨在利用这些技术栈来构建一个现代的、基于Java的Web应用程序。 首先,Spring是Java领域...

    spring mongodb用到的jar包spring-date-mongodb1.4.2.zip

    Spring MongoDB 是一个强大的Java框架,它允许开发人员利用Spring框架的功能来操作MongoDB数据库。这个压缩包`spring-date-mongodb1.4.2.zip`包含了两个核心的JAR文件:`spring-data-mongodb-1.4.2.RELEASE.jar`和`...

    spring data mongodb代码参考

    Spring Data MongoDB是Spring Data项目的一部分,它提供了MongoDB的Repository抽象,允许开发者以声明式的方式定义查询,而无需编写大量的模板代码。通过这个框架,你可以快速地构建基于MongoDB的应用程序,同时...

    spring mongodb很好的例子

    整合Spring Data MongoDB与Spring MVC可以让开发者轻松地在Web应用中使用MongoDB。首先,你需要在项目中添加相关的依赖,包括Spring MVC、Spring Data MongoDB和MongoDB驱动。然后,配置MongoDB数据源,并创建...

    spring-data-mongodb-1.2.0.RELEASE

    在 Spring 应用中使用 Spring Data MongoDB 需要配置 MongoDB 的连接信息,包括主机、端口、数据库名等。通过 @EnableMongoRepositories 注解启用 MongoDB 的仓储接口。 五、对象映射 Spring Data MongoDB 使用 @...

    Spring3+Spring-data-mongodb1.5.6示例

    在本示例中,我们将深入探讨如何在Spring 3框架中集成Spring Data MongoDB 1.5.6,以便高效地处理MongoDB数据库。Spring Data MongoDB是Spring Data项目的一部分,它提供了一个面向对象的API,使得与NoSQL数据库...

    springMongodb参考文档中文版

    - **使用Spring Data MongoDB和MongoDB 3.0**:介绍了如何在MongoDB 3.0环境中使用Spring Data MongoDB。 ### 总结 Spring Data MongoDB是一个强大的工具包,用于简化使用Spring框架和MongoDB的开发工作。它不仅...

    SPRING3.2.4以及依赖包附加MONGODB相关驱动

    标题 "SPRING3.2.4以及依赖包附加MONGODB相关驱动" 提供了关键信息,这是一份关于Spring框架3.2.4版本及其与MongoDB集成的相关依赖包的集合。描述中提到的“绝对齐全能用”意味着这个压缩包包含了所有必要的组件,...

    Spring-Mongodb例子

    总的来说,Spring和MongoDB的结合提供了一个高效、灵活且易于使用的数据存储解决方案,适用于那些需要处理大量非结构化数据或半结构化数据的应用程序。学习和掌握这一组合,将有助于提升开发者在现代Web开发中的技能...

    学生信息系统spring mvc、 maven、 mongodb

    最后,MongoDB是一种流行的NoSQL数据库,以其灵活性和高性能在处理非结构化和半结构化数据时表现出色。在学生信息系统中,MongoDB可以轻松存储如学生个人信息、课程信息、成绩等复杂数据结构。其文档型数据模型允许...

    spring4.2 mongodb 全部jar包

    3. 创建MongoDB模板:使用`MongoFactoryBean`或`MongoClient`创建MongoDB实例,然后通过`MongoTemplate`进行数据库操作。 4. 实现数据访问接口:可以使用`MongoRepository`接口定义CRUD操作,Spring Data会自动实现...

    MongoDB初探(二)----使用spring-data配置mongodb

    在本篇“MongoDB初探(二)----使用spring-data配置mongodb”中,我们将深入探讨如何利用Spring Data框架来集成和操作MongoDB数据库。Spring Data是Spring生态系统的一个重要组成部分,它提供了与各种数据存储系统...

Global site tag (gtag.js) - Google Analytics