Spring Boot整合MongoDB

一、前言

这节我们将整合Spring Boot与Mongo DB实现增删改查的功能,并且实现序列递增。MongoDB安装参考《MongoDB安装》,Mongo DB的基本介绍和增删改查的用法可以参考我之前的文章: MongoDB shell 、 MongoDB文档CUD 和 MongoDB 文档查询 。

二、整合MongoDB

新建一个Spring Boot项目,

2.1 引入依赖:

xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

2.2 数据准备

然后可以通过Mongo Shell或者Mongo Compass工具创建一个名称为testdb的数据库,并新增user文档(文档,类似与关系型数据库里的数据表):

2.3 application.yml配置

在配置文件里配置Mongo DB:

yml 复制代码
spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      database: testdb

Mongo DB的默认端口为27017,使用的数据库为刚刚创建的testdb。

2.4 编码

2.4.1 创建User实体
java 复制代码
@Setter
@Getter
@Document(collection = "user")
public class User {

    @Id
    private String id;

    private String name;

    private Integer age;

    private String description;

}

@Document(collection = "user")表明这是一个文档对象,名称为user,对应Mongo DB里的user表。@Id标注主键字段,String类型的主键值在插入的时候Mongo DB会帮我们自动生成。如果对象中的某个属性为非表字段,可以使用注解@Transient进行排除。

准备好这些后,我们开始编写一些简单的增删改查样例。

2.4.2 创建UserDao接口
java 复制代码
@Repository
public interface UserDao extends MongoRepository<User, String> {
}

接口继承自MongoRepository,泛型分别为实体对象和主键类型。通过继承MongoRepository,UserDao包含了一些增删改查的方法,如下图所示:

2.4.2 编写UserService

UserService.java

java 复制代码
public interface UserService {
    List<User> getUsers();
    Optional<User> getUser(String id);
    User createUser(User user);
    void deleteUser(String id);
    void updateUser(String id, User user);
}

实现类

UserServiceImpl.java

java 复制代码
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public List<User> getUsers() {
        return this.userDao.findAll();
    }

    @Override
    public Optional<User> getUser(String id) {
        return this.userDao.findById(id);
    }

    @Override
    public User createUser(User user) {
        user.setId(null);
        return userDao.save(user);
    }

    @Override
    public void deleteUser(String id) {
        this.userDao.findById(id)
                .ifPresent(user -> this.userDao.delete(user));
    }

    @Override
    public void updateUser(String id, User user) {
        this.userDao.findById(id)
                .ifPresent(
                        u -> {
                            u.setName(user.getName());
                            u.setAge(user.getAge());
                            u.setDescription(user.getDescription());
                            this.userDao.save(u);
                        }
                );
    }
}

上面我们编写了基本的增删改查样例,新增和修改都是通过save方法完成的,当主键存在时则为修改,主键不存在则为新增。

2.4.3 编写controller

最后编写一个RESTful的UserController(为了方便,没有对参数进行校验):

java 复制代码
@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping
    public List<User> getUsers() {
        return userService.getUsers();
    }

    @PostMapping
    public User createUser(User user) {
        return userService.createUser(user);
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable String id) {
        userService.deleteUser(id);
    }

    @PutMapping("/{id}")
    public void updateUser(@PathVariable String id, User user) {
        userService.updateUser(id, user);
    }

    /**
     * 根据用户 id查找
     * 存在返回,不存在返回 null
     */
    @GetMapping("/{id}")
    public User getUser(@PathVariable String id) {
        return userService.getUser(id).orElse(null);
    }
}

2.5 测试

2.5.1 测试新增用户

新增成功,查看数据:

查询成功。

2.5.2 测试通过用ID查找用户
2.5.3 更新用户

查看数据是否更新成功:

2.5.4 删除用户

最后测试通过用户ID删除用户:

返回状态码200,删除成功。

查看数据,删除成功:

三、多条件查询

3.1 UserDao

其实UserDao通过继承MongoRepository已经具有了JPA的特性,我们可以通过方法名来构建多查询条件的SQL。比如通过用户的年龄段来查询:

java 复制代码
List<User> findByAgeBetween(Integer from, Integer to);

在输入findBy后,IDEA会根据实体对象的属性和SQL的各种关键字自动组合提示:

比如再在创建一个通过年龄段,用户名和描述(模糊查询)查询用户的方法:

java 复制代码
List<User> findByAgeBetweenAndNameEqualsAndDescriptionIsLike(Integer from, Integer to, String name, String description);

方法参数个数需要和方法名中所需要的参数个数对应上。

3.1 Service

多条件使用,在UserService里新增一个getUsersByAgeBewteen、findByAgeBetweenAndNameEqualsAndDescriptionIsLik方法:

java 复制代码
    List<User> getUsersByAgeBewteen(Integer from, Integer to);
    List<User> findByAgeBetweenAndNameEqualsAndDescriptionIsLike(Integer from, Integer to, String name, String description);

同时在UserServiceImpl里实现getUsersByAgeBewteen、findByAgeBetweenAndNameEqualsAndDescriptionIsLik方法:

java 复制代码
    @Override
    public List<User> getUsersByAgeBewteen(Integer from, Integer to) {
        return this.userDao.findByAgeBetween(from, to);
    }

    @Override
    public List<User> findByAgeBetweenAndNameEqualsAndDescriptionIsLike(Integer from, Integer to, String name, String description) {
        return this.userDao.findByAgeBetweenAndNameEqualsAndDescriptionIsLike(from, to, name, description);
    }

3.3 Controller

java 复制代码
    @GetMapping("/conditionAgeBetween")
    public List<User> findByAgeBetween(int from, int to) {
        return userService.getUsersByAgeBewteen(from, to);
    }


    @GetMapping("/AgeBetweenAndNameAndDescription")
    public List<User> findByAgeBetweenAndNameEqualsAndDescriptionIsLike(int from, int to, String name, String description) {
        return userService.findByAgeBetweenAndNameEqualsAndDescriptionIsLike(from, to, name, description);
    }

3.4 启动测试

重启项目,我们往数据库里多加几条数据:

测试多条件查询

四、排序与分页

4.1 Service

排序和分页需要使用MongoTemplate对象来完成,在UserService里新增一个getUserByCondition方法:

java 复制代码
Page<User> getUserByCondition(int size, int page, User user);

同时在UserServiceImpl里实现getUserByCondition方法:

java 复制代码
    @Override
    public Page<User> getUserByCondition(int size, int page, User user) {
        Query query = new Query();
        Criteria criteria = new Criteria();
        if (!StringUtils.isEmpty(user.getName())) {
            criteria.and("name").is(user.getName());
        }
        if (!StringUtils.isEmpty(user.getDescription())) {
            criteria.and("description").regex(user.getDescription());
        }
        query.addCriteria(criteria);
        Sort sort = Sort.by("age");
        Pageable pageable = PageRequest.of(page, size, sort);
        List<User> users = template.find(query.with(pageable), User.class);
        return PageableExecutionUtils.getPage(users, pageable, () -> template.count(query, User.class));
    }

size表示每页显示的条数,page表示当前页码数,0表示第一页。上面的方法通过name和description(模糊查询)来查询用户分页信息,并且查询结果使用age字段降序排序。方法返回Page对象。

4.2 Controller

在UserController里添加:

java 复制代码
    @GetMapping("/condition")
    public Page<User> getUserByCondition(int size, int page, User user) {
        return userService.getUserByCondition(size, page, user);
    }

4.3 测试

我们查询description含有"测试"的数据

结果返回有2(totalElements)条记录

我们查询description含有"使用"的数据

结果返回有3条记录

同时翻页

相关推荐
念何架构之路2 分钟前
Go reflect包值操作 Value 的读写、可设置性与 interface 布局
开发语言·后端·golang
小林ixn5 分钟前
用 FastAPI + SQLAlchemy 从零手搓一个博客系统:一套能落地、能讲清楚的 RESTful 后端
后端·python·fastapi
不识君13 分钟前
esl-client 2.0.0 发布:Java 项目接入 FreeSWITCH,从引入到使用
spring boot·后端·开源
牧瀬クリスだ29 分钟前
Redis五大数据类型全解析:从入门到实战
java·数据库·redis·后端·缓存
二宝哥41 分钟前
03.Spring AI Embedding 实战:从向量化原理到项目落地
人工智能·spring boot·向量·spring ai
Rain的Java大神之路1 小时前
北漂 13 年,我把 Java 家底钉成了这张知识图谱(全站免费)
java·后端·程序员
Amos_Web1 小时前
通过 Rspack 源码学 Rust(一):`mod`、`pub` 与 `use crate`/`use super`
后端
张彦峰ZYF1 小时前
拆得开不等于该拆开:微服务与模块化单体的边界判据、规模阈值、团队适配与一致性代价
后端·微服务·边界是否稳定·扩展天花板是否到顶·有无小组能独立值班·独立部署的自由会否被用上·这一刀是否切断不可降级的不变量
是江迪呀1 小时前
介绍一个开源项目 —— 烂笔头
前端·后端
captain3762 小时前
Spring Web MVC(2)
java·前端·spring boot·后端·spring·mvc