【MongoDB】3. springboot整合MongoDB实战测试

本文详细介绍使用SpringBoot集成MongoDB的过程,包括依赖导入、配置文件编写、实体类定义及CRUD操作实现等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 假装这是个前言

在前面的博客中我写了MongoDB Shell基本指令操作,而在开发中,我们通常是用代码去操作数据库的,对于java来说有许多的方式去操作数据库,一个是用Java原生的JDBC接口,要去下载MongoDB的jdbc驱动包,但我们开发往往不会使用原生的jdbc,原生的jdbc每一次操作都得自己建立起连接,想要细细了解MongoDB的jdbc驱动的可以点这个MongoDB Driver官方帮助文档进行学习,所以我们这一篇博客,写的是用springboot去整合MongoDB,springboot里面自带了一个MongoDB的依赖,叫spring-data-mongo

帮助文档:https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#reference

API帮助文档:https://docs.spring.io/spring-data/mongodb/docs/current/api/

2. 演示

2.1 导入依赖

导入spring-data-mongodb依赖

        <!--MongoDb依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
            <version>2.6.2</version>
        </dependency>

目录结构如下
在这里插入图片描述

2.2 编写配置文件

编写配置文件application.yaml

spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      database: test
#      我这里的数据库没有设用户名和密码,所以密码和用户名就没指定了
#      也可以用下面这种方式写,效果等同于上面的host port database分开写的效果
#      uri: mongodb://localhost:27017/person
server:
  port: 8888

2.3 编写映射实体类

PersonInfo.java

package edu.jsu.mongodemo.pojo.dto;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.io.Serializable;
import java.util.List;

/**
 * @author Mo
 * @createTime 2022/1/20 15:41
 * @description
 */
@Data
@Document(collection = "person")
public class PersonInfo implements Serializable {
    //  标记主键
    @Id
    private String  id;
    //  标记字段
    @Field
    private String name;
    //  可以映射数据库内字段名称
    @Field(value = "score_list")
    private List<SubjectScore> subjectScoreList;
}

@Id - 用于字段级别,标记这个字段是一个主键,默认生成的名称是“_id”

@Document - 用于类,以表示这个类需要映射到数据库,您也可以指定映射到数据库的集合名称

@DBRef - 用于字段,以表示它将使用com.mongodb.DBRef进行存储。

@Indexed - 用于字段,表示该字段需要如何创建索引

@CompoundIndex - 用于类,以声明复合索引

@GeoSpatialIndexed - 用于字段,进行地理位置索引

@TextIndexed - 用于字段,标记该字段要包含在文本索引中

@Language - 用于字段,以设置文本索引的语言覆盖属性。

@Transient - 默认情况下,所有私有字段都映射到文档,此注解将会去除此字段的映射

@PersistenceConstructor - 标记一个给定的构造函数,即使是一个protected修饰的,在从数据库实例化对象时使用。构造函数参数通过名称映射到检索的DBObject中的键值。

@Value - 这个注解是Spring框架的一部分。在映射框架内,它可以应用于构造函数参数。这允许您使用Spring表达式语言语句来转换在数据库中检索的键值,然后再用它来构造一个域对象。为了引用给定文档的属性,必须使用以下表达式:@Value("#root.myProperty"),root要指向给定文档的根。

@Field - 用于字段,并描述字段的名称,因为它将在MongoDB BSON文档中表示,允许名称与该类的字段名不同。

@Version - 用于字段锁定,保存操作时检查修改。初始值是0,每次更新时自动触发。??

SubjectScore.java

package edu.jsu.mongodemo.pojo.dto;

import org.springframework.data.mongodb.core.mapping.Field;

/**
 * @author Mo
 * @createTime 2022/1/23 15:43
 * @description
 */
@Data
public class SubjectScore {
    @Field("subject_name")
    private String subjectName;
    private Double score;
}

2.4 CRUD编写

2.4.1 Bson文档格式
/* 1 */
{
    "_id" : ObjectId("61ed0eafc2da593110662f7e"),
    "name" : "mo",
    "scoreList" : [ 
        {
            "subjectName" : "语文",
            "score" : 83
        }, 
        {
            "subjectName" : "数学",
            "score" : 150
        }, 
        {
            "subjectName" : "英语",
            "score" : 666
        }
    ],
    "_class" : "edu.jsu.mongodemo.pojo.dto.PersonInfo"
}

/* 2 */
{
    "_id" : ObjectId("61ed5c816d978a6bfe8b50a3"),
    "name" : "C4ptainMo",
    "scoreList" : [ 
        {
            "subjectName" : "语文",
            "score" : 104
        }, 
        {
            "subjectName" : "数学",
            "score" : 114
        }, 
        {
            "subjectName" : "英语",
            "score" : 118
        }
    ],
    "_class" : "edu.jsu.mongodemo.pojo.dto.PersonInfo"
}

/* 3 */
{
    "_id" : ObjectId("61ed5cb36d978a6bfe8b50a4"),
    "name" : "ProphetMo",
    "scoreList" : [ 
        {
            "subjectName" : "语文",
            "score" : 104
        }, 
        {
            "subjectName" : "数学",
            "score" : 99
        }, 
        {
            "subjectName" : "英语",
            "score" : 134
        }
    ],
    "_class" : "edu.jsu.mongodemo.pojo.dto.PersonInfo"
}
2.4.2 Controller层
package edu.jsu.mongodemo.controller;

import edu.jsu.mongodemo.pojo.dto.PersonInfo;
import edu.jsu.mongodemo.pojo.vo.CommonResult;
import edu.jsu.mongodemo.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author Mo
 * @createTime 2022/1/20 23:23
 * @description
 */
@RestController
@RequestMapping("/test")
public class TestController {
    @Autowired
    private TestService testService;

    @PostMapping("/add")
    public CommonResult addPerson(@RequestBody PersonInfo personInfo) {
        return testService.addPerson(personInfo);
    }

    @PostMapping("/delete")
    public CommonResult deletePerson(@RequestParam("Id")String Id) {
        return testService.deletePerson(Id);
    }

    @PostMapping("/updateScore")
    public CommonResult updatePersonScore(@RequestParam("Id")String Id, @RequestParam("score")Integer score) {
        return testService.updatePersonScore(Id, score);
    }

    @GetMapping("/queryAllPerson")
    public CommonResult queryAllPerson() {
        return testService.queryPersonList();
    }

    @PostMapping("/queryById")
    public CommonResult queryPersonById(@RequestParam("Id")String Id) {
        return testService.queryPersonById(Id);
    }
}
2.4.2 Service层

因为是演示,我就直接把实现写在Service里面了

package edu.jsu.mongodemo.service;

import edu.jsu.mongodemo.dao.TestDao;
import edu.jsu.mongodemo.pojo.dto.PersonInfo;
import edu.jsu.mongodemo.pojo.vo.CommonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author Mo
 * @createTime 2022/1/21 0:51
 * @descripton
 */
@Service
public class TestService {
    @Autowired
    private TestDao testDao;

    public CommonResult addPerson(PersonInfo personInfo) {
        testDao.addPerson(personInfo);
        return new CommonResult(200, "添加成功");
    }

    public CommonResult deletePerson(String Id) {
        testDao.deletePerson(Id);
        return new CommonResult(200, "删除成功");
    }

    public CommonResult updatePersonScore(String Id, Integer score) {
         testDao.updatePersonScore(Id, score);
         return new CommonResult(200, "修改成功");
    }

    public CommonResult queryPersonById(String Id) {
        return new CommonResult(200, "查询成功", testDao.findPersonById(Id));
    }

    public CommonResult queryPersonList() {
        return new CommonResult(200, "查询成功", testDao.queryPersonList());
    }
}
2.4.3 dao层编写
package edu.jsu.mongodemo.dao;

import edu.jsu.mongodemo.pojo.dto.PersonInfo;

import java.util.List;

/**
 * @author Mo
 * @createTime 2022/1/22 16:07
 * @description 使用mongodbTemplate进行数据操作,适合复杂的数据操作,推荐使用
 */
public interface TestDao {
    void addPerson(PersonInfo personInfo);

    void deletePerson(String id);

    void updatePersonScore(String id, Integer score, String subjectName);

    List<PersonInfo> queryPersonList();

    PersonInfo findPersonById(String id);
}

dao层实现层

package edu.jsu.mongodemo.dao.daoImpl;

import com.mongodb.client.result.UpdateResult;
import edu.jsu.mongodemo.dao.TestDao;
import edu.jsu.mongodemo.pojo.dto.PersonInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
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 java.io.Serializable;
import java.util.List;

/**
 * @author Mo
 * @createTime 2022/1/22 16:07
 * @description
 */
@Repository
public class TestDaoImpl implements TestDao {
    @Autowired
    private MongoTemplate mongoTemplate;

    private static final Log log = LogFactory.getLog(TestDaoImpl.class);

    @Override
    public void addPerson(PersonInfo personInfo) {
//        有两种mongoTemplate提供的CRUD方法,
//        一套需要指明操作的集合,一套不需要指明,
//        根据传入映射对象的注释来判断,
//        例如PersonInfo类,如果没有@Document注释那么默认为类名作为集合名插入
//        mongoTemplate.insert(personInfo);
        Serializable person1 = mongoTemplate.insert(personInfo, "person");
        //  输出序列化对象
        log.info(person1);
    }

    @Override
    public void deletePerson(String id) {
        Serializable andRemove = mongoTemplate.findAndRemove(Query.query(
                Criteria.where("id").is(id)
        ), PersonInfo.class, "person");
        log.info(andRemove);
    }

    @Override
    public void updatePersonScore(String id, Integer score, String subjectName) {
        Query query = new Query(Criteria.where("id").is(id)
                //  在查询里面写出子查询条件
                .and("scoreList.subjectName").is(subjectName));
        //  这个update方法相当于一个静态工厂,会生成一个Update对象,并执行set方法,上面的那个Criteria.where()同理
        Update update = Update.update("scoreList.$.score", score);

        //  写法1
        PersonInfo oldPersonInfo = mongoTemplate.update(PersonInfo.class)
                //  匹配符合query的对象
                .matching(query)
                //  修改操作
                .apply(update)
                //  执行
                .findAndModifyValue();
        //  输出执行修改前的数据
        log.info("old PersonInfo: " + oldPersonInfo);

        PersonInfo newPersonInfo = mongoTemplate.query(PersonInfo.class)
                .matching(query)
                .oneValue();
        //  输出修改后的数据
        log.info("new PersonInfo: " + newPersonInfo);
        PersonInfo personInfo = mongoTemplate.update(PersonInfo.class)
                .matching(query)
                .apply(Update.update("scoreList.$.score", 100))
                //  用这个可以添加修改时的选项,这里是返回修改后的值,区别于上面那个修改
                .withOptions(FindAndModifyOptions.options().returnNew(true))
                .findAndModifyValue();
        log.info("optional update result: " + personInfo);

        //  写法2
        UpdateResult updateResult = mongoTemplate.updateFirst(query, Update.update("scoreList.$.score", 666), PersonInfo.class);
        log.info("update result: " + updateResult);
    }

    @Override
    public List<PersonInfo> queryPersonList() {
        List<PersonInfo> personInfoList = mongoTemplate.findAll(PersonInfo.class, "person");
        log.info("queried PersonInfoList: " + personInfoList);
        return personInfoList;
    }

    @Override
    public PersonInfo findPersonById(String id) {
        PersonInfo one = mongoTemplate.findOne(Query.query(Criteria.where("id").is(id)), PersonInfo.class, "person");
        log.info(one);
        return one;
    }
}

期间遇到了许多问题,比如说集合里面的名字命名规范最好不要有下划线“_”,不然无法识别会报错,再然后就是文档的子嵌套查询,查询方式可以看我写的更新操作,我一直在想那个update的filterArray()方法咋用,在StackOverflow上也找了半天,下次等有时间去好好看看官方文档,不过最后还是解决了这个问题,在Query里面就限定好要查询的内容就行,被这么个问题卡这么久,血压都升上来了。

至此,spring-data-mongodb已经入门上手了,还有个分页查询我没写着里面来,等下次有时间再更新下分页查询的写法,其实也很简单就是query().skip(/ 跳过的数据数 /).limit(/每一页的数据量/)这样就实现了分页查询哈哈哈哈哈,下次详细说说,溜了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值