一、前言 这节我们将整合Spring Boot与Mongo DB实现增删改查的功能,并且实现序列递增。MongoDB安装参考 《MongoDB安装》 ,Mongo DB的基本介绍和增删改查的用法可以参考我之前的文章: MongoDB shell 、 MongoDB文档CUD 和 MongoDB 文档查询 。
二、整合MongoDB 新建一个Spring Boot项目,
2.1 引入依赖: 1 2 3 4 5 6 7 8 9 <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:
1 2 3 4 5 6 spring: data: mongodb: host: localhost port: 27017 database: testdb
Mongo DB的默认端口为27017,使用的数据库为刚刚创建的testdb。
2.4 编码 2.4.1 创建User实体 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @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接口 1 2 3 @Repository public interface UserDao extends MongoRepository<User, String> { }
接口继承自MongoRepository,泛型分别为实体对象和主键类型。通过继承MongoRepository,UserDao包含了一些增删改查的方法,如下图所示:
2.4.2 编写UserService UserService.java
1 2 3 4 5 6 7 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 @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(为了方便,没有对参数进行校验):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @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。比如通过用户的年龄段来查询:
1 List<User> findByAgeBetween(Integer from, Integer to);
在输入findBy后,IDEA会根据实体对象的属性和SQL的各种关键字自动组合提示:
比如再在创建一个通过年龄段,用户名和描述(模糊查询)查询用户的方法:
1 List<User> findByAgeBetweenAndNameEqualsAndDescriptionIsLike(Integer from, Integer to, String name, String description);
方法参数个数需要和方法名中所需要的参数个数对应上。
3.1 Service 多条件使用,在UserService里新增一个getUsersByAgeBewteen、findByAgeBetweenAndNameEqualsAndDescriptionIsLik方法:
1 2 List<User> getUsersByAgeBewteen(Integer from, Integer to); List<User> findByAgeBetweenAndNameEqualsAndDescriptionIsLike(Integer from, Integer to, String name, String description);
同时在UserServiceImpl里实现getUsersByAgeBewteen、findByAgeBetweenAndNameEqualsAndDescriptionIsLik方法:
1 2 3 4 5 6 7 8 9 @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 1 2 3 4 5 6 7 8 9 @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方法:
1 Page<User> getUserByCondition(int size, int page, User user);
同时在UserServiceImpl里实现getUserByCondition方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @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里添加:
1 2 3 4 @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条记录
同时翻页