Spring整合组件_MongoDB
MongoDB简介
MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
特点:高性能、易部署、易使用,存储数据非常方便。
主要功能特性:
? 面向集合存储,易存储对象类型的数据
? 模式自由
? 支持动态查询
? 支持完全索引,包含内部对象
? 支持复制和故障恢复
? 使用高效的二进制数据存储,包括大型对象(如视频等)
? 自动处理碎片,以支持云计算层次的扩展性
? 文件存储格式为BSON(一种JSON的扩展)
不足:MongoDB作为一个非关系型数据库有其局限性。MongoDB不支持事务操作,所以需要用到事务的应用建议不用MongoDB,另外MongoDB目前不支持join操作,需要复杂查询的应用也不建议使用MongoDB。
mongodb是属于内存还是硬盘存储?
mongodb的数据是存储在硬盘上的,只不过需要经常读取的数据会被加载到内存中,这样提高查询效率,即所谓的内存数据映射,所以mongodb本身很吃内存。不过MongoDB3.0版本以后会好很多。
快速入门
pom配置
<dependency> <groupId>org.mongodbgroupId> <artifactId>mongo-java-driverartifactId> <version>3.12.1version> dependency> <dependency> <groupId>org.springframework.datagroupId> <artifactId>spring-data-mongodbartifactId> <version>2.0.2.RELEASEversion> dependency> <dependency> <groupId>com.github.jsqlparsergroupId> <artifactId>jsqlparserartifactId> <version>4.0version> dependency> <dependency> <groupId>com.github.pagehelpergroupId> <artifactId>pagehelperartifactId> <version>5.2.0version> dependency>
配置MongoDB
import com.mongodb.MongoClient; import com.mongodb.MongoCredential; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoClientFactoryBean; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; @EnableMongoRepositories @ComponentScan(basePackages = "com.spring.mongodb.repository") //指定@Repository注解的包 @Configuration public class MongoDBConfig { /** * 创建MongoClient * * @return * @throws Exception */ @Bean public MongoClientFactoryBean mongoClient() throws Exception { MongoClientFactoryBean mongoClientFactoryBean = new MongoClientFactoryBean(); mongoClientFactoryBean.setHost("127.0.0.1"); mongoClientFactoryBean.setPort(27017); MongoCredential credential = MongoCredential.createCredential("root", "test", "root".toCharArray()); mongoClientFactoryBean.setCredentials(new MongoCredential[]{credential}); return mongoClientFactoryBean; } /** * 配置MongoTemplate基于模板的访问 * * @param mongoClient * @return */ @Bean public MongoTemplate mongoTemplate(MongoClient mongoClient) { return new MongoTemplate(mongoClient, "test"); } }
基础操作类 MongodbDao
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Repository; import com.github.pagehelper.PageInfo; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; /** * mongodb 基础操作类 * * @param* @author linhongwei */ @Repository public class MongodbDaoextends IdEntity> { private static final Logger logger = LoggerFactory.getLogger(MongodbDao.class); private static final int DEFAULT_SKIP = 0; private static final int DEFAULT_LIMIT = 200; private Class entityClass; @Autowired protected MongoTemplate mongoTemplate; public MongodbDao() { //通过反射机制获取泛型的类类型 Type type = this.getClass().getGenericSuperclass(); // generic 泛型 if(type instanceof ParameterizedType){ // 强制转化“参数化类型” ParameterizedType parameterizedType = (ParameterizedType) type; // 参数化类型中可能有多个泛型参数 Type[] types = parameterizedType.getActualTypeArguments(); // 获取数据的第一个元素(User.class) entityClass = (Class ) types[0]; // com.oa.shore.entity.User.class } } // ======= 增 ============ public void save(T t) { mongoTemplate.save(t); logger.debug("save entity: {}", t); } public void insertAll(List list) { mongoTemplate.insertAll(list); } // ======= 删 ============ /** * 删除对象 * * @param t */ public void delete(T t) { mongoTemplate.remove(t); } /** * 根据id 删除对象 * * @param id */ public void deleteById(String id) { Criteria criteria = Criteria.where("id").is(id); Query query = new Query(criteria); mongoTemplate.remove(query, entityClass); } /** * 根据条件删除 */ public void delete(Query query) { mongoTemplate.remove(query, entityClass); } /** * 删除该collection 的所有的数据 */ public void deleteAll() { mongoTemplate.dropCollection(entityClass); } // ======= 改 ============ public void update(Query query, Update update) { mongoTemplate.findAndModify(query, update, entityClass); } // ======= 查 ============ public List findAll() { return mongoTemplate.findAll(entityClass); } /** * 根据查询query 查找list * * @param query * @return */ public List find(Query query) { return mongoTemplate.find(query, entityClass); } /** * 按照字段排序 - 顺序
* * @param query 查询条件
* @param properties 排序字段
* @return */ public ListfindWithOrderAsc(Query query, String... properties) { Sort sort = new Sort(Direction.ASC, properties); query.with(sort); return mongoTemplate.find(query, entityClass); } /** * 按照字段排序 - 逆序
* * @param query 查询条件
* @param properties 排序字段
* @return */ public ListfindWithOrderDesc(Query query, String... properties) { Sort sort = new Sort(Direction.DESC, properties); query.with(sort); return mongoTemplate.find(query, entityClass); } /** * 根据查询query 查找一个对象 * * @param query * @return */ public T findOne(Query query) { return mongoTemplate.findOne(query, entityClass); } /** * 根据 id 查询对象 * * @param id * @return */ public T findById(String id) { return mongoTemplate.findById(id, entityClass); } /** * 根据id 和 集合名字查询对象 * * @param id * @param collectionName * @return */ public T findById(String id, String collectionName) { return mongoTemplate.findById(id, entityClass, collectionName); } /** * 查询分页 tips:[不要skip 太多的页数,如果跳过太多会严重影响效率。最大不要skip 20000页] * * @param page * @param query * @return */ public PageInfo findPage(PageInfo page, Query query) { long count = this.count(query); page.setTotal(count); int pageNumber = page.getPageNum(); int pageSize = page.getPageSize(); query.skip((pageNumber - 1) * pageSize).limit(pageSize); List list = this.find(query); page.setList(list); return page; } public long count(Query query) { return mongoTemplate.count(query, entityClass); } /** * 获取collection的名字,默认是dao范型T的名字
* 例如: StudentScoreDao extends MongodbDao <StudentScore>
* 则返回的名字是:StudentScore * * @return */ private String getCollectionName() { return entityClass.getSimpleName(); } }
基础实体类 IdEntity
import java.io.Serializable; /** * 实体基础类,所有的实体都继承该类 * @author linhongwei */ public class IdEntity implements Serializable { private static final long serialVersionUID = -8279493522154678891L; private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } }
测试
1、实体类 StudentScore
import java.io.Serializable; import java.util.List; /** * 测试实体类 * @author linhongwei */ public class StudentScore extends IdEntity implements Serializable { private static final long serialVersionUID = 1126745404897398026L; /** * 学生姓名 */ private String username; /** * 学生成绩 */ private ListscoreList; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public List getScoreList() { return scoreList; } public void setScoreList(List scoreList) { this.scoreList = scoreList; } @Override public String toString() { return "StudentScore{" + "username='" + username + '\'' + ", scoreList=" + scoreList + '}'; } }
2、实体类的dao操作类 StudentScoreDao
import com.spring.mongodb.MongodbDao; import com.spring.mongodb.document.StudentScore; import org.springframework.stereotype.Repository; /** * 继承MongodbDao
* 此类对StudentScore对增删改查和分页方法都已经有了
* @author linhongwei */ @Repository public class StudentScoreDao extends MongodbDao{ }
3、测试验证
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes={RootConfig.class, WebConfig.class}) //如果是Java Config配置的,指定相关的配置类 @WebAppConfiguration public class MongoDbTest { @Autowired private StudentScoreDao studentScoreDao; @Test public void test(){ StudentScore studentScore = new StudentScore(); studentScore.setUsername("hello"); studentScore.setId("1234567"); studentScore.setScoreList(Arrays.asList(95d, 97d, 78d)); studentScoreDao.save(studentScore); StudentScore info = studentScoreDao.findById("1234567"); System.out.println(info.toString()); } }
MongoTemplate API
常用的方法:
- mongoTemplate.findAll(Student.class): 查询Student文档的全部数据
- mongoTemplate.findById(
, Student.class): 查询Student文档id为id的数据 - mongoTemplate.find(query, Student.class);: 根据query内的查询条件查询
- mongoTemplate.upsert(query, update, Student.class): 修改
- mongoTemplate.remove(query, Student.class): 删除
- mongoTemplate.insert(student): 新增
Query对象:
(1) 创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
(2) 精准条件:criteria.and(“key”).is(“条件”) ;模糊条件:criteria.and(“key”).regex(“条件”)
(3) 封装条件:query.addCriteria(criteria)
(4) 大于(创建新的criteria):Criteria gt = Criteria.where(“key”).gt(“条件”)
小于(创建新的criteria):Criteria lt = Criteria.where(“key”).lt(“条件”)
(5) Query.addCriteria(new Criteria().andOperator(gt,lt));
(6) 一个query中只能有一个andOperator()。其参数也可以是Criteria数组。
(7) 排序 :query.with(new Sort(Sort.Direction.ASC, "age"). and(new Sort(Sort.Direction.DESC, "date")))