组件整合之MongoDB

MongoDB简介

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

特点:高性能、易部署、易使用,存储数据非常方便。

主要功能特性:

  • 面向集合存储,易存储对象类型的数据
  • 模式自由
  • 支持动态查询
  • 支持完全索引,包含内部对象
  • 支持复制和故障恢复
  • 使用高效的二进制数据存储,包括大型对象(如视频等)
  • 自动处理碎片,以支持云计算层次的扩展性
  • 文件存储格式为BSON(一种JSON的扩展)

不足:MongoDB作为一个非关系型数据库有其局限性。MongoDB不支持事务操作,所以需要用到事务的应用建议不用MongoDB,另外MongoDB目前不支持join操作,需要复杂查询的应用也不建议使用MongoDB

mongodb是属于内存还是硬盘存储?

mongodb的数据是存储在硬盘上的,只不过需要经常读取的数据会被加载到内存中,这样提高查询效率,即所谓的内存数据映射,所以mongodb本身很吃内存。不过MongoDB3.0版本以后会好很多。

快速入门

pom配置

<!-- MongoDB驱动-->
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.12.1</version>
</dependency>
<!--spring-data-mongodb-->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>2.0.2.RELEASE</version>
</dependency>

<!--分页组件-->
<dependency>
    <groupId>com.github.jsqlparser</groupId>
    <artifactId>jsqlparser</artifactId>
    <version>4.0</version>
</dependency>

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.2.0</version>
</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 <T>
 * @author linhongwei
 */
@Repository
public class MongodbDao<T extends 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<T> 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<T>) 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<T> 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<T> findAll() {
        return mongoTemplate.findAll(entityClass);
    }

    /**
     * 根据查询query 查找list
     *
     * @param query
     * @return
     */
    public List<T> find(Query query) {
        return mongoTemplate.find(query, entityClass);
    }

    /**
     * 按照字段排序 - 顺序  <br/>
     *
     * @param query      查询条件  <br/>
     * @param properties 排序字段  <br/>
     * @return
     */
    public List<T> findWithOrderAsc(Query query, String... properties) {
        Sort sort = new Sort(Direction.ASC, properties);
        query.with(sort);
        return mongoTemplate.find(query, entityClass);
    }


    /**
     * 按照字段排序 - 逆序 <br/>
     *
     * @param query      查询条件  <br/>
     * @param properties 排序字段  <br/>
     * @return
     */
    public List<T> findWithOrderDesc(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<T> findPage(PageInfo<T> 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<T> list = this.find(query);
        page.setList(list);
        return page;
    }

    public long count(Query query) {
        return mongoTemplate.count(query, entityClass);
    }

    /**
     * 获取collection的名字,默认是dao范型T的名字 <br/>
     * 例如: StudentScoreDao extends MongodbDao <b>&lt;StudentScore&gt;</b> <br/>
     * 则返回的名字是:<b>StudentScore</b>
     *
     * @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 List<Double> scoreList;
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public List<Double> getScoreList() {
        return scoreList;
    }
 
    public void setScoreList(List<Double> 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<br/>
 * 此类对StudentScore对增删改查和分页方法都已经有了<br/>
 * @author linhongwei
 */
@Repository
public class StudentScoreDao extends MongodbDao<StudentScore> {

}

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(<id>, 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")))

 

posted @ 2022-01-03 20:28  残城碎梦  阅读(174)  评论(0编辑  收藏  举报