SpriingBoot整合MongoDB多数据源

背景:

MongoDB多数据源:springboot为3以上版本,spring-boot-starter-data-mongodb低版本MongoDBFactory已过时,
改为MongoDatabaseFactory。

1、pom引入:

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

在这里插入图片描述
2、结构:

在这里插入图片描述
3、连接配置

spring:
  data:
    mongodb:
      primary:
        uri: mongodb://admin:admin!8@192.168.10.112:27017/kuname?authSource=admin&readPreference=primary&appname=MongoDB Compass Community&ssl=false

4、具体内容

package com.hh.framework.config;

import com.hh.framework.page.MongoPageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;

/**
 * @Description:mongo监听 新增时消除默认添加的 _class 字段保存实体类类型
 **/
@Configuration
public class ApplicationReadyListener implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    @Qualifier("primaryMongo")
    MongoTemplate primaryMongoTemplate;

    /*@Autowired
    @Qualifier("secondaryMongo")
    MongoTemplate secondaryMongoTemplate;
*/
    private static final String TYPEKEY = "_class";

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        MongoConverter converter = primaryMongoTemplate.getConverter();
        if (converter.getTypeMapper().isTypeKey(TYPEKEY)) {
            ((MappingMongoConverter) converter).setTypeMapper(new DefaultMongoTypeMapper(null));
        }
       /* MongoConverter converter2 = secondaryMongoTemplate.getConverter();
        if (converter2.getTypeMapper().isTypeKey(TYPEKEY)) {
            ((MappingMongoConverter) converter2).setTypeMapper(new DefaultMongoTypeMapper(null));
        }*/
    }

    @Bean
    public MongoPageHelper mongoPageHelper() {
        return new MongoPageHelper(primaryMongoTemplate);
    }

}

package com.hh.framework.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;

@Configuration
public class MongoDbConfig {
    @Autowired
    MongoDatabaseFactory mongoDatabaseFactory;
    public @Bean MongoTemplate mongoTemplate() throws Exception {
        //remove _class(insert数据时,mongodb默认生成_class字段)
        MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDatabaseFactory), new MongoMappingContext());
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));
        return new MongoTemplate(mongoDatabaseFactory, converter);
    }

}

package com.hh.framework.config;

import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * @Description:mongo连接配置类
 **/
@Configuration
public class MongoInit {
    @Bean(name = "primaryMongoProperties")
    @Primary
    @ConfigurationProperties(prefix = "spring.data.mongodb.primary")
    public MongoProperties statisMongoProperties() {
        System.out.println("-------------------- primaryMongoProperties init ---------------------");
        return new MongoProperties();
    }

   /* @Bean(name = "secondaryMongoProperties")
    @ConfigurationProperties(prefix = "spring.data.mongodb.secondary")
    public MongoProperties twoMongoProperties() {
        System.out.println("-------------------- secondaryMongoProperties init ---------------------");
        return new MongoProperties();
    }*/

}

package com.hh.framework.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

/**
 * @Description:monngo第一个数据源:primary
 **/
@Slf4j
@Configuration
//jar中含有此类,但此处引入冒红,不影响使用
@EnableMongoRepositories( basePackages = "com.hh.framework.entity.primary",mongoTemplateRef = "primary")
public class PrimaryMongoTemplate {



    @Autowired
    @Qualifier("primaryMongoProperties")
    private MongoProperties primaryMongoProperties;

    @Primary
    @Bean(name = "primaryMongo") //第一个数据源名字oneMongo
    public MongoTemplate primaryMongoTemplate() {

        try {
            log.info("primaryMongoProperties:" + primaryMongoProperties.getUri());
            return new MongoTemplate(mongoDatabaseFactory(primaryMongoProperties));

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Bean
    @Primary
    public MongoDatabaseFactory mongoDatabaseFactory(MongoProperties mongoProperties) {
        return new SimpleMongoClientDatabaseFactory(mongoProperties.getUri());
    }

}

package com.hh.framework.config;

/*import com.mongodb.MongoClientURI;*/
/*import org.springframework.data.mongodb.core.SimpleMongoDbFactory;*/
/*
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
*/

/**
 * @Description: mongo第二个数据源:secondary
 **/
/*
@Configuration
@EnableMongoRepositories(
        basePackages = "com.hh.framework.entity.secondary",
        mongoTemplateRef = "secondary")
 */
public class SecondaryMongoTemplate {

/*
    @Autowired
    @Qualifier("secondaryMongoProperties")
    private MongoProperties secondaryMongoProperties;

    @Primary
    @Bean(name = "secondaryMongo") //第二个数据源名字
    public MongoTemplate primaryMongoTemplate() {

        try {
            log.info("secondaryMongoProperties:" + secondaryMongoProperties.getUri());
            return new MongoTemplate(mongoDatabaseFactory(secondaryMongoProperties));

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Bean
    @Primary
    public MongoDatabaseFactory mongoDatabaseFactory(MongoProperties mongoProperties) {
        return new SimpleMongoClientDatabaseFactory(mongoProperties.getUri());
    }*/
}


package com.hh.framework.entity.primary;

import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.Date;


@Document(collection = "t_city")
@Data
public class CityEntity {

    private String id;

    private String code;

    private String name;
}

5、以下为工具类:

package com.hh.framework.page;


import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * MongoDB分页查询工具类.
 **/
@Component
public class MongoPageHelper {

    public static final int FIRST_PAGE_NUM = 1;
    public static final String ID = "_id";
    private final MongoTemplate mongoTemplate;

    @Autowired
    public MongoPageHelper(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    /**
     * 分页查询,直接返回集合类型的结果.
     *
     * @see MongoPageHelper#pageQuery(Query,
     * Class, Function, Integer, Integer,
     * String)
     */
    public <T> MongoPageResult<T> pageQuery(Query query, Class<T> entityClass, Integer pageSize,
                                       Integer pageNum) {
        return pageQuery(query, entityClass, Function.identity(), pageSize, pageNum, null);
    }

    /**
     * 分页查询,不考虑条件分页,直接使用skip-limit来分页.
     *
     * @see MongoPageHelper#pageQuery(Query,
     * Class, Function, Integer, Integer,
     * String)
     */
    public <T, R> MongoPageResult<R> pageQuery(Query query, Class<T> entityClass, Function<T, R> mapper,
                                          Integer pageSize, Integer pageNum) {
        return pageQuery(query, entityClass, mapper, pageSize, pageNum, null);
    }

    /**
     * 分页查询.
     *
     * @param query Mongo Query对象,构造你自己的查询条件.
     * @param entityClass Mongo collection定义的entity class,用来确定查询哪个集合.
     * @param mapper 映射器,你从db查出来的list的元素类型是entityClass, 如果你想要转换成另一个对象,比如去掉敏感字段等,可以使用mapper来决定如何转换.
     * @param pageSize 分页的大小.
     * @param pageNum 当前页.
     * @param lastId 条件分页参数, 区别于skip-limit,采用find(_id>lastId).limit分页.
     * 如果不跳页,像朋友圈,微博这样下拉刷新的分页需求,需要传递上一页的最后一条记录的ObjectId。 如果是null,则返回pageNum那一页.
     * @param <T> collection定义的class类型.
     * @param <R> 最终返回时,展现给页面时的一条记录的类型。
     * @return PageResult,一个封装page信息的对象.
     */
    public <T, R> MongoPageResult<R> pageQuery(Query query, Class<T> entityClass, Function<T, R> mapper,
                                          Integer pageSize, Integer pageNum, String lastId) {
        //分页逻辑
        long total = mongoTemplate.count(query, entityClass);
        final Integer pages = (int) Math.ceil(total / (double) pageSize);
        if (pageNum <= 0 || pageNum > pages) {
            pageNum = FIRST_PAGE_NUM;
        }
        final Criteria criteria = new Criteria();
        if (StringUtils.isNotBlank(lastId)) {
            if (pageNum != FIRST_PAGE_NUM) {
                criteria.and(ID).gt(new ObjectId(lastId));
            }
            query.limit(pageSize);
        } else {
            int skip = pageSize * (pageNum - 1);
            query.skip(skip).limit(pageSize);
        }

        final List<T> entityList = mongoTemplate
                .find(query.addCriteria(criteria)
                                .with(Sort.by(Lists.newArrayList(new Order(Direction.ASC, ID)))),
                        entityClass);

        final MongoPageResult<R> pageResult = new MongoPageResult<>();
        pageResult.setTotal(total);
        pageResult.setPages(pages);
        pageResult.setPageSize(pageSize);
        pageResult.setPageNum(pageNum);
        pageResult.setList(entityList.stream().map(mapper).collect(Collectors.toList()));
        return pageResult;
    }

}


package com.hh.framework.page;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * 分页结果.
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(Include.NON_NULL)
public class MongoPageResult<T> {

    @Schema(description = "页码,从1开始")
    private Integer pageNum;

    @Schema(description = "页面大小")
    private Integer pageSize;

    @Schema(description = "总数")
    private Long total;

    @Schema(description = "总页数")
    private Integer pages;

    @Schema(description = "数据")
    private List<T> list;

}


package com.hh.framework.page;


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * 分页结果.
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(Include.NON_NULL)
public class MongoPageResult<T> {

    @Schema(description = "页码,从1开始")
    private Integer pageNum;

    @Schema(description = "页面大小")
    private Integer pageSize;

    @Schema(description = "总数")
    private Long total;

    @Schema(description = "总页数")
    private Integer pages;

    @Schema(description = "数据")
    private List<T> list;

}

6、业务模块使用:service层


    @Autowired
    @Qualifier("primaryMongo")
    private MongoTemplate primaryMongoTemplate;


    @Override
    public List getList() {

        Criteria criteria = Criteria.where("id").in().and("code").gte("").lte("");
        Query query = Query.query(criteria).with(Sort.by(Sort.Direction.DESC,"code"));
        return primaryMongoTemplate.find(query, CityEntity.class);
    }

相关推荐

  1. SpringBoot整合Mybatis实现数据配置

    2024-04-08 06:02:02       9 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-08 06:02:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-08 06:02:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-08 06:02:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-08 06:02:02       18 阅读

热门阅读

  1. PDF格式解析:使用CID、CMAP定义字符映射

    2024-04-08 06:02:02       15 阅读
  2. 全球化业务的网络安全挑战

    2024-04-08 06:02:02       16 阅读
  3. Github 2024-04-07 开源项目日报 Top10

    2024-04-08 06:02:02       12 阅读
  4. 机器学习--分类算法

    2024-04-08 06:02:02       11 阅读
  5. MySQL从入门到精通——基础篇

    2024-04-08 06:02:02       12 阅读
  6. Vim脚本语言入门:打造你的编辑器

    2024-04-08 06:02:02       16 阅读
  7. cdn背后nginx 设置获取真实IP及安全配置

    2024-04-08 06:02:02       11 阅读
  8. 3.5Shell_Expansions

    2024-04-08 06:02:02       20 阅读