Spring Boot - 数据库集成05 - 集成MongoDB

Spring Boot集成MongoDB

使用Spring Data 框架都是按照面向对象思想操作用于的工具。

使用Spring Data Mongodb 也是使用面向对象的方式进行操作MongoDB,省略了使用Mongodb的Java客户端API把Document转换为实体类的过程

在这里插入图片描述

一:使用前的准备

1:依赖导入 & 配置

<!-- spring-boot-data-mongodb -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
spring:
  data:
    mongodb:
      host: localhost # mongodb的服务器ip
      port: 27017 # 服务端口号,默认是27017
      # username: cui # 用户名
      # password: 123456 # 密码
      database: test # 当前项目连接的数据库;
      # url: mongodb://cui:123456@192.168.229.137:27017/test # url是前五项的合集写法
      
      # authentication-database: test # 认证的数据库(连接用的账号,不在连接的库下时使用);
      # auto-index-creation: on # 是否自动创建索引的配置;

      # ---------- 副本集写法,必须是写在url中
      # connect:连接模式,指定为replicaSet代表连接副本集群;
      # slaveOk:从节点是否可读,为true表示可读,执行语句时,读操作自动发往从节点;
      # replicaSet:副本集群的名称,这里为cui;
      # --> mongodb://cui:123456 <- 用户名:密码
      # uri: mongodb://cui:123456@192.168.229.137:27018,192.168.229.137:27019,192.168.229.137:27020/test?connect=replicaSet&slaveOk=true&replicaSet=cui

      # ---------- 分片集群配置,必须写在url中,不需要跟option参数
      # ---------- 只需要配置所有mongo所在的IP、端口即可
      # uri: mongodb://cui:123456@192.168.229.137:27024,192.168.229.137:27025/test

2:实体类创建

package com.cui.springmongodemo.entity;

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

import java.io.Serializable;

/**
 * <p>
 * 功能描述:实体类
 * ---------- 各个注解作用范围和含义如下
 * /@Document:作用于类上面,被该注解修饰的类,会和MongoDB中的集合相映射,如果类名和集合名不一致,可以通过collection参数来指定。
 * /@Id:标识一个字段为主键,可以加在任意字段上,但如果该字段不为_id,每次插入需要自己生成全局唯一的主键;如果不设置@Id主键,MongoDB会默认插入一个_id值来作为主键。
 * /@Transient:被该注解修饰的属性,在CRUD操作发生时,SpringData会自动将其忽略,不会被传递给MongoDB。
 * /@Field:作用于普通属性上,如果Java属性名和MongoDB字段名不一致,可以通过该注解来做别名映射。
 * /@DBRef:一般用来修饰“嵌套文档”字段,主要用于关联另一个文档。
 * /@Indexed:可作用于任意属性上,被该注解修饰的属性,如果MongoDB中还未创建索引,在第一次插入时,SpringData会默认为其创建一个普通索引。
 * /@CompoundIndex:作用于类上,表示创建复合索引,可以通过name参数指定索引名,def参数指定组成索引的字段及排序方式。
 * /@GeoSpatialIndexed、@TextIndexed:和上面的@Indexed注解作用相同,前者代表空间索引,后者代表全文索引。
 * </p>
 *
 * @author cui haida
 * @date 2023/11/25/16:43
 */
@Data
@Document(collection = "animals") // @Document -> 作用于类上面,被该注解修饰的类,会和MongoDB中的集合相映射
public class Animals implements Serializable {
   

    private static final long serialVersionUID = 1L;

    @Id // 标识一个字段为主键,可以加在任意字段上,但如果该字段不为_id,每次插入需要自己生成全局唯一的主键
    private Integer id;

    private String name;

    private Integer age;

    private String color;

    private Food food;
}
package com.cui.springmongodemo.entity;

import lombok.Data;

import java.io.Serializable;

/**
 * <p>
 * 功能描述:演示对象
 * </p>
 *
 * @author cui haida
 * @date 2023/11/25/16:45
 */
@Data
public class Food implements Serializable {
   

    private static final long serialVersionUID = 1L;

    private String name;
    private String grade;
}

二:核心 - MongoRepository

基本操作都在这里,只要你的命名足够规范

自定义方法名开头 + 方法名开头跟的关键字 + 字段名 + 字段名称后面可以接的关键字

在这里插入图片描述

package com.cui.springmongodemo.repository;

import com.cui.springmongodemo.entity.Animals;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.DeleteQuery;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * 通过标准名写法自动生成语句
 *
 * @author cui haida
 * @date 2023/11/25/16:47
 */
@Repository
public interface AnimalsRepository extends MongoRepository<Animals, Integer> {
   
    // 查询指定年龄的动物的数量
    Integer countByAge(Integer age);

    // 对动物的名称进行全模糊查询
    List<Animals> findByNameLike(String keyword);

    // 查询时同时满足年龄和姓名两个条件
    Animals findByAgeAndName(int age, String name);

    // 查询满足颜色、年龄其中任一条件的所有动物
    List<Animals> findByColorOrAge(String color, int age);

    // 查询第一个带有颜色的动物
    Animals findFirstByColorNotNull();

    // 查询年龄大于等于指定岁数的动物
    List<Animals> findByAgeGreaterThanEqual(int age);

    // 对id进行多值查询
    List<Animals> findByIdIn(List<Integer> ids);

    // 查询指定颜色的动物,并按照年龄降序返回
    List<Animals> findByColorOrderByAgeDesc(String color);

    // 查询年龄小于指定岁数的前三条数据
    List<Animals> findTop3ByAgeLessThan(int age);

    // 分页查询
    Page<Animals> findByAgeNotNull(Pageable pageable);

    // 注解式写法,自定义
    // @Query这用于自定义查询语句,其中声明根据name字段进行查询
    // ?0表示方法参数的索引(占位符),此处的0表示第一个参数name
    
    // 除此之外,还有另外几个注解,分别对应其他操作:
    // @Update:用于自定义更新语句的注解;
    // @DeleteQuery:用于自定义删除语句的注解;
    // @CountQuery:用于自定义统计语句的注解;
    // @ExistsQuery:用于自定义查询语句,但执行后只返回是否存在满足条件的数据,并不返回具体的文档;
    // @Aggregation:用于自定义聚合管道语句的注解;
    @Query("{'age': {$lt: ?0}}") // age要比传入的参数小才满足条件
    List<Animals> queryXxx(int age);
}
package com.cui.springmongodemo.service;

import com.cui.springmongodemo.entity.Animals;
import org.springframework.data.domain.Page;

import java.util.List;

/**
 * <p>
 * 功能描述:
 * </p>
 *
 * @author cui haida
 * @date 2023/11/25/16:49
 */
public interface AnimalsService {
   
    /**
     * 新增保存动物
     * @param animals 动物对象
     */
    void save(Animals animals);

    /**
     * 通过id删除
     * @param id 要删除的对象的id
     */
    void deleteById(Integer id);

    /**
     * 更新动物
     * @param animals 要更新的动物
     */
    void update(Animals animals);

    /**
     * 通过id返回指定的动物
     * @param id 要查询的动物的id
     * @return 查询到的动物对象
     */
    Animals findById(Integer id);

    /**
     * 拿到集合中的所有的动物对象
     * @return 所有的动物对象
     */
    List<Animals> findAll();

    /**
     * 查询年龄小于指定岁数的前三条数据
     * @param age 年龄
     * @return 年龄小于指定岁数的前三条数据
     */
    List<Animals> findTop3(int age);

    /**
     * 分页测试
     * @param pageNumber 页码
     * @param pageSize 页大小
     * @return 分页结果
     */
    Page<Animals> findByAgeNotNull(int pageNumber, int pageSize);

    /**
     * 自定义注解测试
     * @param age 年龄
     * @return 返回 < 输入年龄的动物集合
     */
    List<Animals> queryXxx(int age);

    /**
     * 事务测试
     */
    void mongoTransaction();
}
package com.cui.springmongodemo.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.cui.springmongodemo.entity.Animals;
import com.cui.springmongodemo.repository.AnimalsRepository;
import com.cui.springmongodemo.service.AnimalsService;
import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;

/**
 * <p>
 * 功能描述:逻辑层实现类
 * </p>
 *
 * @author cui haida
 * @date 2023/11/25/16:53
 */
@Service
@Slf4j
public class AnimalsServiceImpl implements AnimalsService {
   

    @Resource
    private AnimalsRepository animalsRepository;

    @Resource
    private MongoClient mongoClient;

    @Override
    public void save(Animals animals) {
   
        animalsRepository.save(animals);
    }

    @Override
    public void deleteById(Integer id) {
   
        animalsRepository.deleteById(id);
    }

    @Override
    public void update(Animals animals) {
   
        animalsRepository.save(animals);
    }

    @Override
    public Animals findById(Integer id) {
   
        Optional<Animals> animals = animalsRepository.findById(id);
        if (animals.isPresent()) {
   
            return animals.get();
        } else {
   
            log.info("没有找到对应的实体");
            return null;
        }
    }

    @Override
    public List<Animals> findAll() {
   
        return animalsRepository.findAll();
    }

    @Override
    public List<Animals> findTop3(int age) {
   
        return animalsRepository.findTop3ByAgeLessThan(age);
    }

    @Override
    public Page<Animals> findByAgeNotNull(int pageNumber, int pageSize) {
   
        PageRequest pageRequest = PageRequest.of(pageNumber, pageSize);
        return animalsRepository.findByAgeNotNull(pageRequest);
    }

    @Override
    public List<Animals> queryXxx(int age) {
   
        return animalsRepository.queryXxx(age);
    }

    // 其实很少用mongo的事务机制
    @Override
    public void mongoTransaction() {
   
        // 1.先通过mongoClient开启一个session会话
        ClientSession session = mongoClient.startSession();
        try{
   
            // 2.通过session开启事务
            session.startTransaction();

            // 3.创建一个实体对象
            Animals animals = new Animals();
            animals.setId(222);
            animals.setName("白白");
            animals.setColor("白色");
            animals.setAge(1);

            // 4.通过mongoClient获取集合对象
            MongoCollection<Document> collection = mongoClient.getDatabase("test").getCollection("animals");

            // 5.通过集合对象提供的insert方法插入数据
            collection.insertOne(
                    session,
                    Document.parse(JSONObject.toJSONString(animals))
            );

            // 6.模拟执行异常
            int n = 100 / 0;

            // 7.如果执行到这里,说明执行没报错,提交事务
            session.commitTransaction();
        } catch (Exception e) {
   
            // 8.如果进入了catch,说明出现异常,回滚事务
            session.abortTransaction();
            e.printStackTrace();
        }
        // 9.关闭前面开启的session会话
        session.close();
    }
}

三:核心 - MongoTemplate

1:集合操作

一:创建集合

// 要创建集合的名称,collectionOptions -> 参数
mongoTemplate.createCollection(collectionName, [collectionOptions]);

public Integer createCollectionFixedSize(String collectionName, Long size, Long maxDocCount) {
   
    CollectionOptions collectionOptions = CollectionOptions.empty()
        .capped() // 创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档
        .size(size) // 固定集合指定一个最大值,以千字节计(KB),如果 capped 为 true,也需要指定该字段
        .maxDocuments(maxDocCount); // 指定固定集合中包含文档的最大数量
    mongoTemplate.createCollection(collectionName, collectionOptions);
    return mongoTemplate.collectionExists(collectionName) ? 1 : 0;
}

二:查询集合

// 查询所有的集合的名称
mongoTemplate.getCollectionNames();

// 指定集合是否存在
mongoTemplate.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值