SpringBoot整合MongoDB

此文章建立在Mongodb数据库已安装完成情况下。若服务器(linux系统/redhat)没有安装MongoDB,可查看我的另一篇文章 Centos7 使用Yum源安装MongoDB4.2版本数据库(补:密码配置)

本文章仅仅为单数据源配置,多数据源配置我在下一文中会编写。

本文章使用MongoTemplate而非springdatamongodb(个人感觉使用起来更舒适)

一.准备

创建SpringBoot工程,添加吐下依赖 可在创建工程时nosql那栏选择。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
二.文件配置
(1)YML文件配置

个人习惯使用yml格式对Springboot工程进行配置

mongodb连接配置如下:

无密码连接

spring:
  data:
    mongodb:
      uri: mongodb://服务器IP:端口/数据库

有密码连接

spring:
  data:
    mongodb:
      uri: mongodb://用户名:密码@服务器IP:端口/数据库# 上方为明确指定某个数据的用户进行连接
      # 也可以使用admin 数据库中的用户进行连接  统一到admin 数据库进行认证
      # admin 用户认证 url 写法: mongodb://账户:密码%40@ip:端口/数据库名?authSource=admin&authMechanism=SCRAM-SHA-1

mongodb数据库与mysql不一样 mysql 一个普通用户可以管理多个数据库,但是mongo每一个库都有一个独立的管理用户,连接时需要输入对应用户密码

(2)MongoDB监听配置

此类若不加,那么插入的一行会默认添加一个_class字段来存储实体类类型 如(com.example.demo.entity.Student)

/**
 * @author lei
 * @version 1.0
 * @date 2020/02/16 11:22
 * @desc: 监听芒果 保存数据
 */
@Configuration
public class ApplicationReadyListener implements ApplicationListener<ContextRefreshedEvent> {

  @Autowired
  MongoTemplate oneMongoTemplate;
  
  private static final String TYPEKEY = "_class";

  @Override
  public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
    MongoConverter converter = oneMongoTemplate.getConverter();
    if (converter.getTypeMapper().isTypeKey(TYPEKEY)) {
      ((MappingMongoConverter) converter).setTypeMapper(new DefaultMongoTypeMapper(null));
    }
  }
}
三.pojo实体类,service编写

student 编写以及主键ID注意事项

/**
 * @author : leilei
 * @date : 10:23 2020/2/16
 * @desc :student 实体类
 */
@Data
@Document(collection = "student")  //指定要对应的文档名(表名)
public class Student {

    /*** 自定义mongo主键 加此注解可自定义主键类型以及自定义自增规则
     *  若不加 插入数据数会默认生成 ObjectId 类型的_id 字段
     *  org.springframework.data.annotation.Id 包下
     *  mongo库主键字段还是为_id (本文实体类中字段为为id,意思查询字段为_id,但查询结果_id会映射到实体对象id字段中)
     */
    @Id
    private Long id;
    private String username;
    private LocalDateTime timer;
}

service服务层注入MongoTemplate ,使用MongoTemplate 对Mongo库进行操作

四.MongoTemplate 操作mongo库
(1)新增
public int insertStudent(Student student) {
    student.setTimer(LocalDateTime.now());
    mongoTemplate.insert(student);
    return 1;
}
(2)修改

此文根据Id修改 ,如需其他条件 修改Query 查询条件即可

需注意 Query 以及update 在org.springframework.data.mongodb.core.query 包下

public int updateStudent(Student student) {
    //通过query根据id查询出对应对象,通过update对象进行修改
    Query query = new Query(Criteria.where("_id").is(student.getId()));
    Update update = new Update().set("username", student.getUsername());
    mongoTemplate.updateFirst(query, update, Student.class);
    return 1;
}
(3)删除

此文根据id删除,如需其他删除条件,修改对应Query对象即可

public int removeStudent(Long id) {
    Query query = new Query(Criteria.where("_id").is(id));
    mongoTemplate.remove(query, Student.class);
    return 1;
}
(4)查询一个

我这里查询条件统一为实体类,取字段即可

查询一个精确匹配

根据id/其他(更换query查询条件)

public Student findOne(Student student) {
    Query query = new Query(Criteria.where("_id").is(student.getId()));
    return mongoTemplate.findOne(query, Student.class);
}
(5)查询集合-模糊匹配

查询集合-模糊匹配

根据id/其他(更换query查询条件)

我这里查询条件统一为实体类,取字段即可

注意:Pattern 包路径为 java.util.regex.Pattern;

public List<Student> findLike(Student student) {
    Pattern pattern = Pattern.compile("^.*" + student.getUsername().trim() + ".*$", Pattern.CASE_INSENSITIVE);
    Query query = new Query(Criteria.where("username").regex(pattern));
    return mongoTemplate.find(query, Student.class);
}
(6)查询集合-精确匹配

查询集合-精确匹配

根据id/其他(更换query查询条件)

我这里查询条件统一为实体类,取字段即可

public List<Student> findMore(Student student) {
    Query query = new Query(Criteria.where("username").is(student.getUsername()));
    return mongoTemplate.find(query, Student.class);
}
(7)倒叙排列查询

根据时间倒叙排列查询所有

需注意 :Sort的包路径为 import org.springframework.data.domain.Sort;

SpringBoot2.2.X版本与Mongo整合写法有变动 本文SpringBoot版本为2.1.4

public List<Student> findTime(Student student) {
    Query query = new Query();
    query.with(new Sort(Sort.Direction.DESC, "timer"));
    return mongoTemplate.find(query, Student.class);
}
(8)MongoDB分页查询

mongodb 分页查询需要自己组装查询后的数据(总数 当前页数据 总页数)

分页主要用到 skip 和 limit (类似于mysql的 limit 1 10写法)

需要注意:skip 和java8 Stream 中用法一致,即跳过多少个数据 limit 为取多少条数据 3 则3条 5则五条

package com.example.demo.entity;

import lombok.Data;

/**
 * @author lei
 * @create 2022-08-26 14:51
 * @desc 分页查询表单
 **/
@Data
public class StudentQueryForm {
    private Integer pageIndex;
    private Integer pageSize;
    private String  username;
}

拿去即用的公共分页响应与组装模型

/**
 * @author lei
 * @create 2022-08-26 14:46
 * @desc 分页对象
 **/
@Data
public class PageVO<T> {
    /**
     * 当前页
     */
    private Integer pageIndex;
    /**
     * 当前页最大长度
     */
    private Integer pageSize;
    /**
     * 总数
     */
    private Integer total;
    /**
     * 总页数
     */
    private Integer pages;
    /**
     * 当前页数据
     */
    private List<T> data;


    public static <T> PageVO<T> emptyResult() {
        PageVO<T> page = new PageVO<>();
        page.setPageIndex(1);
        page.setPageSize(10);
        page.setTotal(0);
        page.setPages(0);
        page.setData(new ArrayList<>());
        return page;
    }

    public static <T> PageVO<T> getPageResult(List<T> list, Integer pageIndex, Integer pageSize, Integer countSize) {
        PageVO<T> page = new PageVO<>();
        page.setPageIndex(pageIndex);
        page.setPageSize(pageSize);
        page.setTotal(countSize);
        page.setPages(countSize % pageSize == 0 ? countSize / pageSize : countSize / pageSize + 1);
        page.setData(list);
        return page;
    }
}

分页查询实现具体逻辑

/**
 * mongodb分页查询需要自己拼装一下
 *
 * @param queryForm
 * @return PageVO<Student>
 * @author lei
 * @date 2022-08-26 14:53:43
 */
public PageVO<Student> findByPage(StudentQueryForm queryForm) {

    Query query = new Query();
    if (queryForm.getUsername() != null) {
        query.addCriteria(Criteria.where("username").is(queryForm.getUsername()));
    }
    // 1.根据条件查询总数 总数无数据则反回空数据分页对象
    int count = (int) mongoTemplate.count(query, Student.class);
    if (count < 1) {
        return PageVO.emptyResult();
    }
    query.with(new Sort(Sort.Direction.DESC, "timer"));
    // 2.有数据,则查询指定页数数据 (skip =(当前页-1)*指定页长度)
    int skip = (queryForm.getPageIndex() - 1) * queryForm.getPageSize();
    query.skip(skip).limit(queryForm.getPageSize());
    List<Student> students = mongoTemplate.find(query, Student.class);
    // 3.获取总页数 总数除每页长度
    // 4.拼接返回分页响应
    return  PageVO.getPageResult(students, queryForm.getPageIndex(), queryForm.getPageSize(), count);
}

项目连接:mongodb
MongoDB的基础使用差不多就是这些了,后续的mongo多数据源以及 Aggregation管道高级查询,将继续更新。。。。。。。。。。。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐