SpringBoot2.3使用mongoTemplate整合mongoDb。
读者需要了解maven, lombok,mongDb
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.3.RELEASEversion>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>demoname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>11java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
<exclusions>
<exclusion> <groupId>org.junit.vintagegroupId> <artifactId>junit-vintage-engineartifactId>
exclusion>
exclusions>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
本例以本地的test2数据库为例子,且不开启用户认证。mongodb默认是免认证的,可以去设置开启认证: application.properties如下
#最简单的配置就是直接配置mongdb的本地地址和端口号
spring.data.mongodb.host=127.0.0.1
spring.data.mongodb.port=27017
#如果不配置database,则默认使用test数据库
spring.data.mongodb.database=test2
待会会把这个Bean对象的信息存放到mongDb:
@Data
@Document("User")
public class User {
@Id
private String id;
private String name;
private Integer age;
private String address;
private String createDate;
}
实际上这个接口的所有方法都可以直接放在dao层,看个人习惯,本例子在示例的时候直接加在Service就懒得改了。
/**
* 使用MongoTemplate接口,基本能够完成增删改查操作,包括批量插入,批量修改,模糊查询,删除所有,删除满足条件的;
* 查询满足任一条件的数据,查询满足所有条件的数据;分页查询;查询结果排序
*/
public interface UserService {
/**
* 新增,插入(不能插入相同id的数据)
*
* @param po
* @return
*/
User insertOne(User po);
/**
* 插入多条
*
* @param userList
* @return
*/
Collection<User> insertMany(List<User> userList);
/**
* 修改,如果id存在则修改,如果id不存在则新增
*
* @param po
* @return
*/
User update(User po);
/**
* 修改
*
* @param po
* @return
*/
UpdateResult update2(User po, User newPo);
/**
* 查询一条(即使是有多条数据也只是返回第一条)
*
* @param po
* @return
*/
User findOne(User po);
/**
* 模糊查询一条(即使是有多条数据也只是返回第一条)
*
* @param po
* @return
*/
User findOneLike(User po);
/**
* 查询多条数据
*
* @param po
* @return
*/
List<User> findListLike(User po);
/**
* 模糊查询2
*
* @param po
* @return
*/
List<User> findListLike2(User po);
/**
* 多查询条件模糊查询3
*
* @param po
* @return
*/
List<User> findListLike3(User po);
/**
* 查询结果排序
*
* @param po
* @return
*/
List<User> findListSort(User po);
/**
* 查询满足任意一个条件的多条数据
*
* @param po
* @return
*/
List<User> findListAny(User po);
/**
* 分页查询
*
* @param po
* @return
*/
List<User> findListByPage(User po, int page, int size);
/**
* 删除所有
*/
void deleteAll();
/**
* 删除指定的对象
*/
void delete(User po);
/**
* 根据id删除
*
* @param id
*/
void deleteById(String id);
/**
* 判断是否存在
*
* @param po
* @return
*/
Boolean exists(User po);
}
@Slf4j
@Service
public class UserServiceImpl implements UserService {
@Autowired
private MongoTemplate mongoTemplate;
@Override
public User insertOne(User po) {
return mongoTemplate.insert(po);
}
@Override
public Collection<User> insertMany(List<User> userList) {
Collection<User> insert = mongoTemplate.insert(userList, User.class);
return insert;
}
@Override
public User update(User po) {
// 如果不存在则新增,存在则修改, 要求所有字段必须有值,且必须有id。否则只会新增
return mongoTemplate.save(po);
}
@Override
public UpdateResult update2(User po, User newPo) {
// 如果不存在则新增,存在则修改, 要求所有字段必须有值
Query query = Query.query(Criteria.byExample(Example.of(po)));
// 修改address并且设置age字段加1; update还有一些常用的方法对集合进行增加或减少字段,例如增加字符串字段,减少字符字段,增加日期,数值类型的增减
// 增加字段, 用得比较少,因为一个集合中的对象属性基本都是比较固定的,如果常常变更,则数据难以维护
//update.addToSet(String key);
// 删除字段, 用得比较少,因为一个集合中的对象属性基本都是比较固定的,如果常常变更,则数据难以维护
//update.unset(String key);
// 添加日期, 用得比较少,因为一个集合中的对象属性基本都是比较固定的,如果常常变更,则数据难以维护
// update.currentDate(String key);
// 用得比较多的是数值类型增减inc
Update update = Update.update("address", newPo.getAddress()).inc("age", 1);
// updateFirst方法只对匹配到的第一条数据进行修改
//mongoTemplate.updateFirst(query, update, User.class)
// updateMulti对匹配到的多条数据都进行修改
UpdateResult updateResult = mongoTemplate.updateMulti(query, update, User.class);
// 返回匹配的条数
//updateResult.getMatchedCount();
// 返回修改的条数
///updateResult.getModifiedCount();
return updateResult;
}
@Override
public User findOne(User po) {
// 构造example对象
Example<User> example = Example.of(po);
// 构造Criteria对象
Criteria criteria = Criteria.byExample(example);
// 构造Query查询对象
Query query = Query.query(criteria);
// 查单条数据
User user = mongoTemplate.findOne(query, User.class);
return user;
}
@Override
public User findOneLike(User po) {
// 改变查询模式,改为模糊查询name为包含,address为以什么结尾,其他字段仍然是精确查询
ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains())
.withMatcher("address", ExampleMatcher.GenericPropertyMatchers.endsWith());
// ExampleMatcher.matching().withMatcher()
// 构造example对象
Example<User> example = Example.of(po, exampleMatcher);
// 构造Criteria对象
Criteria criteria = Criteria.byExample(example);
// 构造Query查询对象
Query query = Query.query(criteria);
// 查单条数据
User user = mongoTemplate.findOne(query, User.class);
return user;
}
@Override
public List<User> findListLike(User po) {
ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains())
.withMatcher("address", ExampleMatcher.GenericPropertyMatchers.contains());
// 构造example对象
Example<User> example = Example.of(po, exampleMatcher);
Query query = Query.query(Criteria.byExample(example));
return mongoTemplate.find(query, User.class);
}
@Override
public List<User> findListLike2(User po) {
// 改变默认字符串匹配方式:直接把精确查询改为模糊查询
// 必须是ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);的方式写,
// 不能分开写成ExampleMatcher matcher = ExampleMatcher.matching(); matcher.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
Example<User> example = Example.of(po, matcher);
Query query = Query.query(Criteria.byExample(example));
return mongoTemplate.find(query, User.class);
}
@Override
public List<User> findListLike3(User po) {
// 改变默认字符串匹配方式:直接把精确查询改为模糊查询
// 必须是ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);的方式写,
// 不能分开写成ExampleMatcher matcher = ExampleMatcher.matching(); matcher.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
Example<User> example = Example.of(po, matcher);
//构造多查询条件
/**
* 说明byExample 生成的Criteria如果再接了where和and之后,查询结果则无法查询出example的过滤数据
* 如Criteria criteria = Criteria.byExample(example).where("age").gt(39) 只能查询出age大于39的数据,而其他字段的过滤则不再生效
*/
//Criteria criteria = Criteria.byExample(example);
// .where("age").gt(39);
// 例子1:查询age大于39且name = po.getName的数据 ,这个写法可以
// Criteria criteria = Criteria.where("age").gt(39).and("name").is(po.getName());
// 例子2: 查询age大于39且name = po.getName的数据 ,这个写法可以
Criteria criteria = new Criteria().andOperator(Criteria.where("age").gt(39), Criteria.where("name").is(po.getName()));
// 例子3:查询age大于39或name = po.getName的数据 , 这个写法不行
//Criteria criteria = Criteria.where("age").gt(39).orOperator(Criteria.where("name").is(po.getName()));
// 例子4:查询age大于39或name = po.getName的数据 , 这个写法可以
//Criteria criteria = new Criteria().orOperator(Criteria.where("age").gt(39), Criteria.where("name").is(po.getName()));
// 例子5:查询姓名为张三并且年龄为18岁或者姓名为李四年龄为20的用户
/*Criteria and1 = new Criteria();
and1.andOperator(Criteria.where("name").is("张三"),Criteria.where("age").is(18));
Criteria and2 = new Criteria();
and2.andOperator(Criteria.where("name").is("李四"),Criteria.where("age").is(20));
Criteria c = new Criteria();
c.orOperator(and1,and2);*/
Query query = Query.query(criteria);
return mongoTemplate.find(query, User.class);
}
@Override
public List<User> findListSort(User po) {
// 设置为模糊查询
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
Example<User> example = Example.of(po, matcher);
// 设置排序规则
Sort sort = Sort.by(Sort.Direction.DESC, "address");
Query query = Query.query(Criteria.byExample(example)).with(sort);
return mongoTemplate.find(query, User.class);
}
@Override
public List<User> findListAny(User po) {
// 设置为或模式,默认是且模式,或表示查询条件中的任意一个条件满足都返回。是指不同的查询字段,而不是同一个字段的不同值
ExampleMatcher matcher = ExampleMatcher.matchingAny()
.withMatcher("address", ExampleMatcher.GenericPropertyMatchers.contains());
Example<User> example = Example.of(po, matcher);
Query query = Query.query(Criteria.byExample(example));
return mongoTemplate.find(query, User.class);
}
@Override
public List<User> findListByPage(User po, int page, int size) {
// 改为模糊查询
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains())
.withMatcher("address", ExampleMatcher.GenericPropertyMatchers.contains());
// 测试2: 不写name时,默认应该是精确查询的
/*ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher("address", ExampleMatcher.GenericPropertyMatchers.endsWith());*/
Example<User> example = Example.of(po, matcher);
Criteria criteria = Criteria.byExample(example);
// 构造分页对象
Pageable pageable = PageRequest.of(page, size);
// 构造分页对象,带排序规则
// Pageable pageable = PageRequest.of(page, size, Sort.Direction.DESC, "title");
// Sort sort = Sort.by(Sort.Direction.DESC, "address");
// 不带排序规则
Query query = Query.query(criteria).with(pageable);
// 分页查询
List<User> users = mongoTemplate.find(query, User.class);
return users;
}
@Override
public void deleteAll() {
mongoTemplate.remove(User.class);
}
@Override
public void delete(User po) {
// 构建query对象
Query query = Query.query(Criteria.byExample(Example.of(po)));
// 根据query查询条件进行删除
mongoTemplate.remove(query, User.class);
}
@Override
public void deleteById(String id) {
Query query = Query.query(Criteria.where("id").is(id));
mongoTemplate.remove(query, User.class);
}
@Override
public Boolean exists(User po) {
Example<User> of = Example.of(po);
Query query = Query.query(Criteria.byExample(of));
return mongoTemplate.exists(query, User.class);
}
}
使用SpringBootTest进行测试,lombok记录日志
@Slf4j
@SpringBootTest
public class UserTest {
@Autowired
private UserService userService;
@Test
public void testInsert() {
User po = new User();
po.setName("张三");
po.setAddress("广州");
po.setAge(39);
po.setCreateDate("1991-06-22");
User user = userService.insertOne(po);
log.info("【新增用户】user:{}", user);
}
@Test
public void testInsertMany() {
List<User> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User po = new User();
po.setName("李四" + i);
po.setAddress("广州" + i);
po.setAge(33 + i);
po.setCreateDate("1991-06-22");
list.add(po);
}
Collection<User> users = userService.insertMany(list);
log.info("【新增用户】user:{}", users);
}
@Test
public void testUpdate() {
User po = new User();
po.setName("李四0");
User one = userService.findOne(po);
one.setAddress("李四的深圳住所22");
User update = userService.update(one);
log.info("【修改用户】修改用户: {}", update);
}
@Test
public void testUpdate2() {
User po = new User();
po.setName("李四4");
User newPo = new User();
newPo.setAddress("李四的深圳住所4");
UpdateResult updateResult = userService.update2(po, newPo);
log.info("【修改用户】匹配用户数:{},修改用户数: {}", updateResult.getMatchedCount(), updateResult.getModifiedCount());
}
@Test
public void testIFindOne() {
User po = new User();
po.setName("李四0");
//po.setAge(34);
/*po.setAddress("广州");
po.setAge(33);
po.setCreateDate("1991-06-22");*/
User user = userService.findOne(po);
log.info("【查询用户】user:{}", user);
}
@Test
public void testIFindOneLike() {
User po = new User();
// 模糊查询
po.setAddress("广州");
User user = userService.findOneLike(po);
log.info("【查询用户】user:{}", user);
}
@Test
public void testFindListLike() {
User po = new User();
// 模糊查询地址包含广州的数据
po.setAddress("广州");
List<User> list = userService.findListLike(po);
log.info("【查询用户】user:{}", list);
}
@Test
public void testFindListLike2() {
User po = new User();
// 模糊查询地址包含广州的数据
po.setName("李");
List<User> list = userService.findListLike2(po);
log.info("【查询用户】user:{}", list);
}
@Test
public void testFindListLike3() {
User po = new User();
// 模糊查询地址包含广州的数据
po.setName("李四8");
List<User> list = userService.findListLike3(po);
log.info("【查询用户】user:{}", list);
}
@Test
public void testFindListSort() {
User po = new User();
// 模糊查询地址包含广州的数据
po.setName("李");
List<User> list = userService.findListSort(po);
log.info("【查询用户】user:{}", list);
}
@Test
public void testFindListAny() {
User po = new User();
// 模糊查询地址包含广州的数据
po.setAddress("广州");
po.setName("李四0");
List<User> list = userService.findListAny(po);
log.info("【查询用户】user:{}", list);
}
@Test
public void testFindListByPage() {
User po = new User();
// 模糊查询地址包含广州的数据
po.setAddress("广州");
po.setName("李");
int page = 0;
int size = 3;
List<User> list = userService.findListByPage(po,page, size);
log.info("【查询用户】user:{}", list);
}
@Test
public void testDelete() {
User po = new User();
// 模糊查询地址包含广州的数据
po.setName("李四0");
userService.delete(po);
log.info("【查询用户】user:{}", po);
}
@Test
public void testDeleteById() {
User po = new User();
// 模糊查询地址包含广州的数据
po.setName("张三");
User one = userService.findOne(po);
userService.deleteById(one.getId());
log.info("【查询用户】user:{}", po);
}
@Test
public void testExists() {
User po = new User();
// 模糊查询地址包含广州的数据
po.setName("李四0");
Boolean exists = userService.exists(po);
log.info("【查询用户是否存在】user:{}", exists);
}
}