SpringBoot整合mongodb

一. 概述

参考开源项目https://github.com/xkcoding/spring-boot-demo
此Demo简单集成mongodb,使用官方的 starter 实现增删改查。

二. 安装mongodb

  1. 下载镜像:docker pull mongo
  2. 运行容器:docker run -d -p 27017:27017 --name mongo mongo:latest

三. SpringBoot工程

3.1 依赖

        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-starter-data-mongodb
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
            cn.hutool
            hutool-all
        

3.2 application.yml

spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      database: monge_demo
logging:
  level:
    org.springframework.data.mongodb.core: debug

3.3 启动类

@SpringBootApplication
public class SpringBootDemoMongodbApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoMongodbApplication.class, args);
    }
}

3.4 实体类: Article.java

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Article {
    /**
     * 文章id
     */
    @Id
    private Long id;

    /**
     * 用户ID
     */
    private Long userId;

    /**
     * 文章标题
     */
    private String title;

    /**
     * 文章内容
     */
    private String content;

    /**
     * 创建时间
     */
    private Date createTime;

    /**
     * 更新时间
     */
    private Date updateTime;

    /**
     * 点赞数量
     */
    private Long thumbUp;

    /**
     * 访客数量
     */
    private Long visits;

}

3.5 持久层: ArticleRepository.java

public interface ArticleRepository extends MongoRepository {
    /**
     * 根据标题模糊查询
     *
     * @param title 标题
     * @return 满足条件的文章列表
     */
    List
findByTitleLike(String title); }

注: 可以通过关键字声明方法, 不用写实现
下标源于文章MongoRepository的生成规则

方法关键字 示例 等价于SQL
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1(参数绑定附加%)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1(参数与预先绑定%)
Containing findByFirstnameContaining … where x.firstname like ?1(参数绑定%)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection ages) … where x.age not in ?1
True findByActiveTrue() … where x.active = true
False findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

3.6 简单的CURD

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class ArticleRepositoryTest {
    @Autowired
    private ArticleRepository articleRepo;

    @Autowired
    private MongoTemplate mongoTemplate;

    private static Snowflake snowflake = IdUtil.createSnowflake(1, 1);


    /**
     * 测试新增
     */
    @Test
    public void testSave() {
        Article article = new Article(1L, RandomUtil.randomString(20), RandomUtil.randomString(150), DateUtil.date(), DateUtil.date(), 0L, 0L);
        articleRepo.save(article);
        // 更具ID属性进行新增或更新
        mongoTemplate.save(article);
        log.info("【article】= {}", JSONUtil.toJsonStr(article));
    }

    /**
     * 测试批量新增列表
     */
    @Test
    public void testSaveList() {
        List
articles = Lists.newArrayList(); for (int i = 0; i < 10; i++) { articles.add(new Article(snowflake.nextId(), RandomUtil.randomString(20), RandomUtil.randomString(150), DateUtil.date(), DateUtil.date(), 0L, 0L)); } articleRepo.saveAll(articles); log.info("【articles】= {}", JSONUtil.toJsonStr(articles.stream().map(Article::getId).collect(Collectors.toList()))); } /** * 测试更新 */ @Test public void testUpdate() { articleRepo.findById(1L).ifPresent(article -> { article.setTitle(article.getTitle() + "更新之后的标题"); article.setUpdateTime(DateUtil.date()); articleRepo.save(article); log.info("【article】= {}", JSONUtil.toJsonStr(article)); }); } /** * 测试删除 */ @Test public void testDelete() { // 根据主键删除 articleRepo.deleteById(1L); // 全部删除 articleRepo.deleteAll(); } /** * 测试分页排序查询 */ @Test public void testQuery() { Sort sort = Sort.by("thumbUp", "updateTime").descending(); PageRequest pageRequest = PageRequest.of(0, 5, sort); Page
all = articleRepo.findAll(pageRequest); log.info("【总页数】= {}", all.getTotalPages()); log.info("【总条数】= {}", all.getTotalElements()); log.info("【当前页数据】= {}", JSONUtil.toJsonStr(all.getContent().stream().map(article -> "文章标题:" + article.getTitle() + "点赞数:" + article.getThumbUp() + "更新时间:" + article.getUpdateTime()).collect(Collectors.toList()))); } }

3.7 更新

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class ArticleRepositoryTest {
    @Autowired
    private ArticleRepository articleRepo;

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 测试点赞数、访客数,使用save方式更新点赞、访客
     */
    @Test
    public void testThumbUp() {
        articleRepo.findById(1L).ifPresent(article -> {
            article.setThumbUp(article.getThumbUp() + 1);
            article.setVisits(article.getVisits() + 1);
            articleRepo.save(article);
            log.info("【标题】= {}【点赞数】= {}【访客数】= {}", article.getTitle(), article.getThumbUp(), article.getVisits());
        });
    }

    /**
     * 测试点赞数、访客数,使用更优雅/高效的方式更新点赞、访客
     */
    @Test
    public void testThumbUp2() {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(1L));
        Update update = new Update();
        update.inc("thumbUp", 1L);
        update.inc("visits", 1L);
        mongoTemplate.updateFirst(query, update, "article");

        articleRepo.findById(1L).ifPresent(article -> log.info("【标题】= {}【点赞数】= {}【访客数】= {}", article.getTitle(), article.getThumbUp(), article.getVisits()));
    }
}

3.8 高级查询

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class ArticleRepositoryTest {
    @Autowired
    private ArticleRepository articleRepo;

    @Autowired
    private MongoTemplate mongoTemplate;
    /**
     * 查询,条件匹配/排序/分页, 基于继承MongoRepository实现
     */
    @Test
    public void testQuery1() {
        /**
         * 匹配条件构造
         */
        Article article = Article.builder()
            .title("ayyg6qetc2jigduentiz")
            .content("tx1549k4dbu05ou83tx8te0gx1")
            .build();
        // 指定字段匹配类型
        ExampleMatcher withMatcher = ExampleMatcher.matching()
            // 忽略大小写
            .withIgnoreCase()
            // 指定"title"为精确匹配
            .withMatcher("title", ExampleMatcher.GenericPropertyMatcher::exact)
            // 指定"content"为模糊匹配
            .withMatcher("content", ExampleMatcher.GenericPropertyMatcher::contains);
        Example
example = Example.of(article,withMatcher); /** * 排序规则 */ Sort sort = Sort.by("updateTime").descending(); /** * 分页 */ PageRequest pageRequest = PageRequest.of(0, 5, sort); /** * 分页查询 */ Page
articleRepoAll = articleRepo.findAll(example, pageRequest); /** * 打印 */ log.info(JSONUtil.toJsonStr(articleRepoAll.getContent())); } /** * 查询,条件匹配/排序/分页, 基于MongoTemplate实现 */ @Test public void testQuery2() { /** * 查询条件 */ Criteria criteria = Criteria // 精确匹配 .where("title").is("ayyg6qetc2jigduentiz") // 模糊匹配, 用正则: .*[xxx].* .and("content").regex(".*tx1549k4dbu05ou83tx8te0gx1.*") // 匹配明细里的字段 .and("ids").elemMatch(Criteria.where("id").is(1)) // 匹配多个并行或 .andOperator( new Criteria().orOperator( Criteria.where("visits").exists(false), Criteria.where("visits").is(1) ), new Criteria().orOperator( Criteria.where("thumbUp").exists(false), Criteria.where("thumbUp").is(1) ) ); ; /** * 排序规则 */ Sort sort = Sort.by("updateTime").descending(); /** * 分页 */ PageRequest pageRequest = PageRequest.of(1, 5, sort); Query query = Query.query(criteria).with(sort).with(pageRequest); List
articles = mongoTemplate.find(query, Article.class); PageImpl
page = (PageImpl
) PageableExecutionUtils.getPage(articles, pageRequest, () -> mongoTemplate.count(Query.query(criteria),Article.class)); // 打印 Optional.of(page.getContent()).ifPresent(articles1 -> { articles1.forEach(article -> { log.info("打印数据:{}",JSONUtil.toJsonStr(article)); }); }); } }

3.9 MongoTemplate 实现 联表/分页/排序查询

    public IPage
pageInfo(){ /** * 联表查询 * 参数1: 从表表名 * 参数2: 主表关联字段 * 参数3: 从表关联字段 * 参数4: 查出从表数据集合的别名 例如主表数据{"name":"wpr","age":18} , 关联从表后结果{"name":"wpr","age":18,"userInfo":[]}, 从表没数据则为[] */ LookupOperation lookup = Aggregation.lookup("user", "userId", "userId", "userInfo"); // 子集合不能为空 Criteria criteria = Criteria.where("userInfo").not().size(0); // 子集合条件 criteria.and("userInfo.six").is(1); // 主表条件 criteria.and("title").is("hello_world"); // 条件类型转换 MatchOperation matchOperation = Aggregation.match(criteria); /** * 查询总数 */ CountOperation countOperation = Aggregation.count().as("total"); // project: 表示结果只查询字段:total ProjectionOperation project = Aggregation.project("total"); // 条件一定要排好先后顺序 Aggregation aggregation = Aggregation.newAggregation(lookup, matchOperation, countOperation, project); AggregationResults aggregate = mongoTemplate.aggregate(aggregation, "article", Map.class); List aggregateMappedResults = aggregate.getMappedResults(); // 总数 Integer total = CollectionUtils.isEmpty(aggregateMappedResults) ? 0 : (int)aggregateMappedResults.get(0).get("total"); if(Objects.equals(total,0)){ return new Page<>(); } /** * 分页查询 */ // 排序条件 SortOperation sortOperation = Aggregation.sort(Sort.by("updateTime").descending()); // 过滤前n条数据 SkipOperation skipOperation = Aggregation.skip(0L); // 查询n条数据 LimitOperation limitOperation = Aggregation.limit(10); Aggregation pageAggregation = Aggregation.newAggregation(lookup, matchOperation, sortOperation,skipOperation,limitOperation); AggregationResults
result = mongoTemplate.aggregate(pageAggregation,"article", Article.class); List
articles = result.getMappedResults(); Page
page = new Page<>(); page.setTotal(total); page.setRecords(articles); return page; }

你可能感兴趣的:(SpringBoot整合mongodb)