文章目录
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管道高级查询,将继续更新。。。。。。。。。。。