MongoDB - 整合 SpringBoot 操作全流程

本文详细介绍了如何在SpringBoot项目中整合MongoDB,包括引入依赖、配置连接、集合操作、注解使用、文档操作(查询、分页、排序、更新、删除)以及MongoDB4.0后的事务处理。
该文章已生成可运行项目,

目录

一、MongoDB 整合 SpringBoot

1.1、引入依赖

1.2、配置文件

1.3、集合操作

1.4、相关注解

1.5、文档操作

Tips:重要提示

1.5.1、查询

1.5.2、分页查询 + 排序

1.5.3、更新

1.5.4、删除

1.6、事务


一、MongoDB 整合 SpringBoot


1.1、引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

1.2、配置文件

spring:
  data:
    mongodb:
      uri: mongodb://192.168.73.3:27017/demo
      field-naming-strategy: org.springframework.data.mapping.model.SnakeCaseFieldNamingStrategy # 自动转驼峰

#      mongodb 一般不设置密码
#      username: root
#      password: 1111

uri 格式为: mongodb://ip 地址:mongodb 端口号/集合名

1.3、集合操作

Ps:以 demo 集合为例

a)创建集合

        if(!mongoTemplate.collectionExists("demo")) {
            //不存在才能创建,如果以及存在再创建就会报错
            mongoTemplate.createCollection("demo");
        }

b)删除集合

        mongoTemplate.dropCollection("demo1");

1.4、相关注解

a)@Document

  • 修饰范围:在类上.
  • 作用:映射当前类的一个对象为 mongo 的一条文档.
  • 属性:value 和 collection 都是用来表示操作的集合名.

b)@Id

  • 修饰范围:成员变量、方法.
  • 作用:将值映射成文档的 _id.

c)@Field

  • 修饰范围:成员变量、方法.
  • 作用:将值映射为文档中的一个 key 名称.

d)@Transient

  • 修饰范围:成员变量、方法.
  • 租用:指定值不参与文档序列化.

以 User 类为例:

@Document("demo") //表示当前文档属于哪个集合
public class User {

    @Id //当前类的 id 映射文档中的 _id
    private Integer id;
    private String name;
    private Integer age;
    @Field("work_day")  //当前类的 workDay 映射文档中的 work_day
    private Date workDay;

    public User(Integer id, String name, Integer age, Date workDay) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.workDay = workDay;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", workDay=" + workDay +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getWorkDay() {
        return workDay;
    }

    public void setWorkDay(Date workDay) {
        this.workDay = workDay;
    }
}

1.5、文档操作

Tips:重要提示

mongo 对类型有严格的要求.  例如根据 id 查询用户,你使用 String 类型的 id 作为 查询的参数,而 mongo 文档中保存的是 Long 类型的参数,此时你的查询记不起作用.

这点需要跟 MySQL 区分开!!!

1.5.1、查询

        //1.查询所有
        System.out.println("------------------------------------------------");
        List<User> users = mongoTemplate.findAll(User.class);
        users.forEach(System.out::println);

        //2.根据 id 查询指定文档
        System.out.println("------------------------------------------------");
        User byId = mongoTemplate.findById(1, User.class);
        System.out.println(byId);

        //3.根据查询条件进行查询(参数1: 查询条件, 参数2: 返回类型)
        System.out.println("------------------------------------------------");
//        mongoTemplate.find(new Query(), User.class);  //没有查询条件就是查询所有
        //a) 等值查询
        System.out.println("------------------------------------------------");
        List<User> users1 = mongoTemplate.find(Query.query(Criteria.where("name").is("周杰伦")), User.class);
        users1.forEach(System.out::println);

        //b) > 查询: gt()、>= 查询: gte() 、 < 查询: lt()、<= 查询 lte() 查询
        //以 > 为例
        System.out.println("------------------------------------------------");
        List<User> users2 = mongoTemplate.find(Query.query(Criteria.where("age").gt(30)), User.class);
        users2.forEach(System.out::println);

        //4.and 查询
        System.out.println("------------------------------------------------");
        List<User> users3 = mongoTemplate.find(Query.query(Criteria.where("name").is("薛之谦").and("age").is(40)), User.class);
        users3.forEach(System.out::println);

        //5.or 查询
        System.out.println("------------------------------------------------");
        Criteria criteria = new Criteria();
        criteria.orOperator(
        Criteria.where("name").is("周杰伦"),
                Criteria.where("name").is("薛之谦")
        );
        List<User> users4 = mongoTemplate.find(Query.query(criteria), User.class);
        users4.forEach(System.out::println);

        //6.and 和 or
        System.out.println("------------------------------------------------");
        Criteria criteria1 = new Criteria();
        criteria1.and("age").is(40)
                .orOperator(
                        Criteria.where("name").is("周杰伦"),
                        Criteria.where("name").is("薛之谦")
                );
        List<User> users5 = mongoTemplate.find(Query.query(criteria1), User.class);
        users5.forEach(System.out::println);

        //7.sort
        System.out.println("------------------------------------------------");
        Query query = new Query();
        query.with(Sort.by(Sort.Order.desc("age"))); //desc 降序, asc 升序
        mongoTemplate.find(query, User.class);

        //8.分页: skip limit
        System.out.println("------------------------------------------------");
        Query queryPage = new Query();
        queryPage.with(Sort.by(Sort.Order.desc("age"))) //desc 降序, asc 升序
                .skip(0)
                .limit(3);
        mongoTemplate.find(queryPage, User.class);

        //9.总数
        System.out.println("------------------------------------------------");
        mongoTemplate.count(new Query(), User.class);

        //10.去重 distinct(参数1: 查询条件, 参数2: 去重字段, 参数3: 操作集合, 参数4: 返回类型)
        System.out.println("------------------------------------------------");
        List<String> name = mongoTemplate.findDistinct(new Query(), "name", User.class, String.class);

        //11.json 字符串查询
        System.out.println("------------------------------------------------");
        Query queryJson = new BasicQuery("{name: '周杰伦', age: '20'}");
        List<User> users6 = mongoTemplate.find(queryJson, User.class);

1.5.2、分页查询 + 排序

    public List<MyDocument> findPaginated(int page, int size) {  
        // 创建查询对象  
        Query query = new Query();  
  
        // 添加过滤条件,如果有的话  
        // query.addCriteria(Criteria.where("fieldName").is("value"));  
  
        // 添加排序条件,如果有的话  
        // query.with(Sort.by(Sort.Direction.ASC, "fieldName"));  
  
        // 计算跳过的文档数量  
        long skip = (page - 1) * size;  
  
        // 设置查询的起始位置和返回的数量  
        query.skip(skip).limit(size);  
  
        // 执行查询并返回结果  
        return mongoTemplate.find(query, MyDocument.class, "collectionName");  
    }

1.5.3、更新

更新指定字段的值.

        //1.更新条件
        Query query = Query.query(Criteria.where("name").is("周杰伦"));
        //2.更新内容
        Update update = new Update();
        update.set("age", 20);

        //a) 更新单条
        mongoTemplate.updateFirst(query, update, User.class);
        //b) 更新多条
        mongoTemplate.updateMulti(query, update, User.class);
        //c) 不存在就插入(存在就更新第一条)
        mongoTemplate.upsert(query, update, User.class);

指定某字段自增一,或者自减一.

            mongoTemplate.updateFirst(
                    Query.query(
                            Criteria
                                    .where("_id")
                                    .is(dto.getTargetId())
                    ),
                    new Update().inc("like_cnt", 1), //如果是 -1,就表示自减一
                    AlbumStatGO.class
            );

1.5.4、删除

        //1.删除所有
        mongoTemplate.remove(new Query(), User.class);
        //2.条件删除
        mongoTemplate.remove(Query.query(Criteria.where("name").is("林俊杰")), User.class);

1.6、事务

MongoDB 4.0 之后就支持事务了.

但是开启事务的前提如下:

a)开启集群模式(多副本集配置)

b)进行如下配置:

@Configuration
class MongoTransaction {

    @Bean
    fun transactionManager(factory: MongoDatabaseFactory): MongoTransactionManager {
        return MongoTransactionManager(factory)
    }

}

c)在需要回滚的地方加上 @Transactional 注解 

    @Transactional
    fun handler(dto: RegDto) {
        userIdentRepo.save(dto)
        throw AppException(ApiStatus.INVALID_PARAM, "这里故意触发异常,为了检验事务*-")
        userDetailRepo.save(dto.id!!)
    }

Ps:如果没有进行副本集的配置,就会报如下错误:

本文章已经生成可运行项目
### 如何整合 MongoDB 数据库与 Spring Boot 框架 #### 添加依赖项 为了使 Spring Boot 能够连接并操作 MongoDB,项目中需引入 `spring-boot-starter-data-mongodb` 依赖。这可以通过在项目的构建文件(如 Maven 的 pom.xml 或 Gradle 构建脚本)中添加如下所示的片段实现[^2]。 对于Maven项目: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> ``` #### 配置数据源 接着,在应用程序的主要配置文件 application.properties 或者更推荐使用的 YAML 文件 (application.yml) 中指定 MongoDB 连接字符串和其他必要的参数。下面是一个简单的例子,展示了如何定义不带认证信息的情况下的 URI 地址[^3]。 ```yaml spring: data: mongodb: uri: mongodb://localhost:27017/user ``` 这里的 `uri` 字段指定了主机名(`localhost`)、端口号 (`27017`) 和默认数据库名称 (`user`)。 #### 创建实体类和仓库接口 之后,应该基于业务需求设计相应的 Java 实体类来映射到 MongoDB 文档结构,并通过继承自 `MongoRepository<T,ID>` 接口的方式来声明持久层逻辑。这样做的好处是可以利用内置的方法来进行基本的数据访问操作而无需编写额外代码。 例如,如果有一个名为 User 的文档模型,则对应的 Repository 可能看起来像这样: ```java public interface UserRepository extends MongoRepository<User, String> { } ``` 其中 `<User, String>` 表明该存储库处理的是具有 `_id` 属性类型的 `String` 类型的对象实例。 #### 测试 CRUD 功能 最后一步就是验证整个流程是否正常工作了。可以借助单元测试或者直接运行应用并通过 RESTful API 来执行增删改查等常规动作。确保所有的变更都反映到了实际部署的目标环境中去。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈亦康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值