MongoDB快速上手指南:SpringBoot整合MongoDB
5.1 需求分析
這里會(huì)結(jié)合一個(gè)具體的業(yè)務(wù)場景(小案例),對(duì)用戶評(píng)論進(jìn)行CRUD
在這個(gè)案例中主要的需求是:
- 基本增刪改查API
- 根據(jù)文章id查詢評(píng)論
- 評(píng)論點(diǎn)贊
文章示例參考:早晨空腹喝水,是對(duì)還是錯(cuò)?www.toutiao.com/a6721476546…
5.2 表結(jié)構(gòu)分析
數(shù)據(jù)庫:articledb,集合就用我們上面一直在使用的comment
5.3 技術(shù)選型
5.3.1 mongodb-driver(了解)
mongodb-driver是mongo官方推出的java連接mongoDB的驅(qū)動(dòng)包,相當(dāng)于JDBC驅(qū)動(dòng)。我們通過一個(gè)入門的案例來了解mongodb-driver 的基本使用。
- 官方驅(qū)動(dòng)說明和下載:mongodb.github.io/mongo-java-…
- 官方驅(qū)動(dòng)示例文檔:mongodb.github.io/mongo-java-…
5.3.2 SpringDataMongoDB
SpringData家族成員之一,用于操作MongoDB的持久層框架,封裝了底層的mongodb-driver。
官網(wǎng)主頁: projects.spring.io/spring-data…
5.4 文章微服務(wù)模塊搭建
(1)搭建項(xiàng)目工程article,pom.xml引入依賴:
"1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.2version>
<relativePath/>
parent>
<groupId>com.fxgroupId>
<artifactId>articleartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>articlename>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
plugins>
build>
project>
復(fù)制代碼
(2)創(chuàng)建application.yml
spring:
#數(shù)據(jù)源配置
data:
mongodb:
# 主機(jī)地址
host: localhost
# 數(shù)據(jù)庫
database: articledb
# 默認(rèn)端口是27017
port: 27017
# 也可以使用uri連接
#uri: mongodb://192.168.40.134:27017/articledb
復(fù)制代碼
(3)創(chuàng)建啟動(dòng)類
com.fx.article.ArticleApplication
package com.fx.article;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ArticleApplication {
public static void main(String[] args) {
SpringApplication.run(ArticleApplication.class, args);
}
}
復(fù)制代碼
我們啟動(dòng)一下空項(xiàng)目,看Mongo
連接是否正常,一般就可以正常連接了
5.5 文章評(píng)論實(shí)體類的編寫
創(chuàng)建實(shí)體類 創(chuàng)建包c(diǎn)om.fx.article,包下建包po用于存放實(shí)體類,創(chuàng)建實(shí)體類
這里有一點(diǎn)需要注意,因?yàn)?code>Mongo是可以進(jìn)行橫向拓展的,所以可能會(huì)出現(xiàn)一個(gè)集合對(duì)應(yīng)多個(gè)實(shí)體類的情況
package com.fx.article.po;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
*
* 文檔評(píng)論實(shí)體類
* 把一個(gè)Java類生命為mongodb的文檔,可以通過collection參數(shù)指定這個(gè)類對(duì)應(yīng)的文檔
*
*
* @since 2022-07-28 20:19
* @author 梁峰源
**/
@Data
// 若未添加@Document注解,則該bean save到mongo的comment collection
@Document(collection = "comment")//指定對(duì)應(yīng)的集合,如果省略則默認(rèn)為類名小寫進(jìn)行集合映射
@CompoundIndex(def = "{'userid': 1, 'nickname' : -1}") // 添加復(fù)合索引,先按userid排,再按nickname降序排
public class Comment implements Serializable {
private static final long serialVersionUID = 21218312631312334L;
// 主鍵標(biāo)識(shí),該屬性的值會(huì)自動(dòng)對(duì)應(yīng)mongodb的主鍵字段`_id`, 如果該屬性名叫做 `id`, 則該注解可以省略,否者必須寫
@Id
private String id;//主鍵
private String content;//吐槽內(nèi)容
private Date publishtime;//發(fā)布日期
// 添加了一個(gè)單子段的索引
@Indexed
private String userid;//發(fā)布人的ID
private String nickname;//用戶昵稱
private LocalDateTime createdatetime;//評(píng)論的日期時(shí)間
private Integer likenum;//點(diǎn)贊數(shù)
private Integer replaynum;//回復(fù)數(shù)
private String state;//狀態(tài)
private String parentid;//上級(jí)ID
private String articleid;//文章id
}
復(fù)制代碼
說明: 索引可以大大提升查詢效率,一般在查詢字段上添加索引,索引的添加可以通過Mongo的命令來添加,也可以在Java的實(shí)體類中通過注解添加。一般我們?yōu)榱隧?xiàng)目的可拓展性,會(huì)在命令行進(jìn)行添加
1)單字段索引注解@Indexed
org.springframework.data.mongodb.core.index.Indexed.class
聲明該字段需要索引,建索引可以大大的提高查詢效率。
Mongo命令參考:
JavaScript copyable" lang="javascript">db.comment.createIndex({"userid":1})
復(fù)制代碼
2)復(fù)合索引注解@CompoundIndex
org.springframework.data.mongodb.core.index.CompoundIndex.class
復(fù)合索引的聲明,建復(fù)合索引可以有效地提高多字段的查詢效率。
Mongo命令參考:
db.comment.createIndex({"userid":1,"nickname":-1})
復(fù)制代碼
5.6 文章評(píng)論的基本增刪改查
(1)創(chuàng)建數(shù)據(jù)訪問接口 cn.itcast.article包下創(chuàng)建dao包,包下創(chuàng)建接口
com.fx.article.dao.CommentRepository
package com.fx.article.dao;
import com.fx.article.po.Comment;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
*
*
*
*
* @author 梁峰源
* @since 2022-07-28 20:34
**/public interface CommentRepository extends MongoRepository {
}
復(fù)制代碼
(2)創(chuàng)建業(yè)務(wù)邏輯類 cn.itcast.article包下創(chuàng)建service包,包下創(chuàng)建類
com.fx.article.service.CommentService
package com.fx.article.service;
import com.fx.article.dao.CommentRepository;
import com.fx.article.po.Comment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
*
* 評(píng)論service方法
*
*
* @since 2022-07-28 20:36
* @author 梁峰源
**/
@Service
public class CommentService {
//注入dao
@Autowired
private CommentRepository commentRepository;
/**
* 保存一個(gè)評(píng)論
*/
public void saveComment(Comment comment) {
//如果需要自定義主鍵,可以在這里指定主鍵;如果不指定主鍵,MongoDB會(huì)自動(dòng)生成主鍵
//設(shè)置一些默認(rèn)初始值。。。
//調(diào)用dao
commentRepository.save(comment);
}
/**
* 更新評(píng)論
*/
public void updateComment(Comment comment) {
//調(diào)用dao
commentRepository.save(comment);
}
/**
* 根據(jù)id刪除評(píng)論
*/
public void deleteCommentById(String id) {
//調(diào)用dao
commentRepository.deleteById(id);
}
/**
* 查詢所有評(píng)論
*/
public List findCommentList() {
//調(diào)用dao
return commentRepository.findAll();
}
/**
* 根據(jù)id查詢評(píng)論
*/
public Comment findCommentById(String id) {
//調(diào)用dao
return commentRepository.findById(id).get();
}
}
復(fù)制代碼
(3)新建Junit測試類,測試保存和查詢所有:
com.fx.itcast.article.service.CommentServiceTest
package com.fx.article.service;
import com.fx.article.po.Comment;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author Eureka
* @version 1.0
* @since 2022年7月28日20:56:33
*/@SpringBootTest
public class CommentServiceTest {
@Autowired
private CommentService commentService;
/**
* 保存一條記錄
*/
@Test
public void testSaveComment() throws Exception {
Comment comment = new Comment();
comment.setArticleid("100000");
comment.setContent("測試添加的數(shù)據(jù)");
comment.setCreatedatetime(LocalDateTime.now());
comment.setUserid("1003");
comment.setNickname("凱撒大帝");
comment.setState("1");
comment.setLikenum(0);
comment.setReplynum(0);
commentService.saveComment(comment);
// 在查詢一下這條記錄,這里獲取id的方式和Mybatis Plus一樣,直接從實(shí)體類中獲取即可
Comment commentById = commentService.findCommentById(comment.getId());
System.out.println(commentById);
}
/**
* 更新一條記錄
*/
@Test
public void testUpdateComment() throws Exception {
// Comment comment = new Comment();
// comment.setId("1");
// comment.setNickname("張三");
// 上面的方式會(huì)將其他字段變?yōu)榭?,所以可以先查詢出來再更新?duì)應(yīng)字段
Comment comment = commentService.findCommentById("1");
comment.setNickname("張三");
// 更新這條記錄
commentService.updateComment(comment);
// 打印一下這條記錄
Comment commentById = commentService.findCommentById(comment.getId());
System.out.println(commentById);
}
/**
* Method: deleteCommentById(String id) */ @Test
public void testDeleteCommentById() throws Exception {
commentService.deleteCommentById("1");
}
/**
* Method: findCommentList() */ @Test
public void testFindCommentList() throws Exception {
List commentList = commentService.findCommentList();
System.out.println(commentList);
}
/**
* 通過id查詢一條記錄
*/
@Test
public void testFindCommentById() throws Exception {
Comment commentById = commentService.findCommentById("1");
System.out.println(commentById);
}
}
復(fù)制代碼
這里需要注意如果是MongoDB 6
以上的版本可能打印不出來,這里可能有像MySQL中MVCC之類的同學(xué),我換成4版本后就可以正常打印出來了
5.7 根據(jù)上級(jí)ID查詢文章評(píng)論的分頁列表
(1)CommentRepository新增方法定義
/**
* 分頁查詢,這里的名字要根據(jù)提示來,不能寫錯(cuò)不然會(huì)生成失敗
*/
Page findByUserid(String userid, Pageable pageable);
復(fù)制代碼
(2)CommentService新增方法
/**
* 根據(jù)父id查詢分頁列表
* @param userid
* @param page 頁碼
* @param size 頁數(shù)
*/
public Page findCommentListPageByUserid(String userid,int page ,int size){
return commentRepository.findByUserid(userid, PageRequest.of(page-1,size));
}
復(fù)制代碼
測試
@Test
void testFindCommentListPageByParentid() {
Page pages = commentService.findCommentListPageByUserid("1003", 1, 3);
// 打印有多少條記錄
System.out.println(pages.getTotalElements());
List contentList = pages.getContent();
// 將所有的記錄都打印出來
contentList.forEach(System.out::println);
}
復(fù)制代碼
5.8 MongoTemplate實(shí)現(xiàn)評(píng)論點(diǎn)贊
我們看一下以下點(diǎn)贊的臨時(shí)示例代碼: CommentService 新增updateThumbup方法
/**
* 點(diǎn)贊-效率低
* @param id
*/
public void updateCommentThumbupToIncrementingOld(String id){
Comment comment = commentRepository.findById(id).get();
comment.setLikenum(comment.getLikenum()+1);
commentRepository.save(comment);
}
復(fù)制代碼
以上方法雖然實(shí)現(xiàn)起來比較簡單,但是執(zhí)行效率并不高,因?yàn)槲抑恍枰獙Ⅻc(diǎn)贊數(shù)加1就可以了,沒必要查詢出所有字段修改后再更新所有字 段。(蝴蝶效應(yīng))
我們可以使用MongoTemplate類來實(shí)現(xiàn)對(duì)某列的操作。
(1)修改CommentService
//注入MongoTemplate
@Autowired
private MongoTemplate mongoTemplate;
/**
* 點(diǎn)贊數(shù)+1
* @param id
*/
public void updateCommentLikenum(String id) {
//查詢對(duì)象
Query query = Query.query(Criteria.where("_id").is(id));
//更新對(duì)象
Update update = new Update();
//局部更新,相當(dāng)于$set
// update.set(key,value) //遞增$inc
// update.inc("likenum",1); update.inc("likenum");
//參數(shù)1:查詢對(duì)象
//參數(shù)2:更新對(duì)象
//參數(shù)3:集合的名字或?qū)嶓w類的類型Comment.class
mongoTemplate.updateFirst(query, update, "comment");
}
復(fù)制代碼
(2)測試用例:
@Test
void testupdateCommentLikenum() {
// 更新之前
System.out.println(commentService.findCommentById("2"));
commentService.updateCommentLikenum("2");
// 更新之后
System.out.println(commentService.findCommentById("2"));
}
復(fù)制代碼
測試結(jié)果,可以看到數(shù)據(jù)已經(jīng)增長了
更多的命令可以自行進(jìn)行查看,這里貼一下API的地址:
- 菜鳥教程
- Spring-data MongoDB官方文檔
作者:是小梁同學(xué)呀
鏈接:https://juejin.cn/post/7126746699527094303
來源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
版權(quán)聲明:
本站所有文章和圖片均來自用戶分享和網(wǎng)絡(luò)收集,文章和圖片版權(quán)歸原作者及原出處所有,僅供學(xué)習(xí)與參考,請勿用于商業(yè)用途,如果損害了您的權(quán)利,請聯(lián)系網(wǎng)站客服處理。