文档章节

SpringBoot 集成MongoDB

zw965
 zw965
发布于 09/22 11:22
字数 3071
阅读 63
收藏 0

一、MongoDB 简介

MongoDB 如今是最流行的 NoSQL 数据库,被广泛应用于各行各业中,很多创业公司数据库选型就直接使用了 MongoDB,但对于大部分公司,使用 MongoDB 的场景是做大规模数据查询和离线分析。MongoDB 一经推出就受到了广大社区的热爱,可以说是对程序员最友好的一种数据库,下面我们来了解一下它的特性。

MongoDB(Humongous,庞大)是可以应用于各种规模的企业、各个行业以及各类应用程序的开源数据库,作为一个适用于敏捷开发的数据库,MongoDB 的数据模式可以随着应用程序的发展而灵活地更新。与此同时,它也为开发人员提供了传统数据库的功能:二级索引、完整的查询系统及严格一致性等。MongoDB 能够使企业更加具有敏捷性和可扩展性,各种规模的企业都可以通过使用 MongoDB 来创建新的应用,来提高与客户之间的工作效率,加快产品上市时间,以及降低企业成本。

MongoDB 是专门为可扩展性、高性能和高可用性而设计的数据库,它可以从单服务器部署扩展到大型、复杂的多数据中心架构。利用内存计算的优势,MongoDB 能够提供高性能的数据读写操作。 MongoDB 的本地复制和自动故障转移功能使应用程序具有企业级的可靠性和操作灵活性。

  • MongoDB 相关概念

  • 在学习 MongoDB 之前需要先了解一些专业术语,常说 MongoDB 是最像关系数据库的 NoSQL 数据库,我们用关系数据库和 MongoDB 做一下对比,方便更清晰地认识它。

MongoDB 和关系数据库一样有库的概念,一个 MongoDB 数据库可以有很多数据库,MongoDB 中的集合就相当于我们关系数据库中的表,文档就相当于关系数据库中的行,域就相当于关系数据库中的列,MongoDB 也支持各种索引有唯一主键,但不支持表连接查询。

二、Spring Boot MongoDB

  • Spring Boot 操作数据库的各种 Starters 都继承于 Spring Data,Spring Data 是 Spring 为了简化数据库操作而封装的一个组件包,提供了操作多种数据库的支持,其 API 简洁、调用方便。

  • spring-boot-starter-data-mongodb 是 Spring Data 的一个子模块。目标是为 MongoDB 提供一个相近的、一致的、基于 Spring 的编程模型。spring-boot-starter-data-mongodb 核心功能是映射 POJO 到 Mongo 的 DBCollection 中的文档,并且提供 Repository 风格数据访问层。

  • 我们使用 Spring Boot 进行 MongoDB 连接,需要使用 spring-boot-starter-data-mongodb 包。spring-boot-starter-data-mongodb 继承 Spring Data 的通用功能外,针对 MongoDB 的特性开发了很多定制的功能,让我们使用 Spring Boot 操作 MongoDB 更加简便。

  • Spring Boot 操作 MongoDB 有两种比较流行的使用方法:

    • 一种是将 MongoTemplate 直接注入到 Dao 中使用;
    • 一种是继承 MongoRepository,MongoRepository 内置了很多方法可直接使用。

1、MongoTemplate 的使用

  • MongoTemplate 提供了非常多的操作 MongoDB 方法,它是线程安全的,可以在多线程的情况下使用。

  • MongoTemplate 实现了 MongoOperations 接口, 此接口定义了众多的操作方法如 find、findAndModify、findOne、insert、remove、save、update and updateMulti 等。它转换 domain object 为 DBObject,并提供了 Query、Criteria and Update 等流式 API。

  • 我们后面在使用动态查询时候会用到 DBObject 对象的操作。

  • (1)pom 包配置

  • pom 包里面添加 spring-boot-starter-data-mongodb 包引用:

<dependencies>
    <dependency> 
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency> 
</dependencies>
  • (2)在 application.properties 中添加配置
spring.data.mongodb.uri=mongodb://name:pass@localhost:27017/test
  • 多个 IP 集群可以采用以下配置:
spring.data.mongodb.uri=mongodb://user:pwd@ip1:port1,ip2:port2/database
  • 当然了密码和用户名如果没有设置可以不用添加,像这样:
spring.data.mongodb.uri=mongodb://localhost:27017/test

注:Mongo 3.0 Java 驱动不支持 spring.data.mongodb.host 和 spring.data.mongodb.port,对于这种情况,spring.data.mongodb.uri 需要提供全部的配置信息。

  • (3)创建数据实体
public class User implements Serializable {
        private static final long serialVersionUID = -3258839839160856613L;
        private Long id;
        private String userName;
        private String passWord;

      //getter、setter 省略
}
  • (4)对实体进行增删改查操作
  • Repository 层实现了 User 对象的增、删、改、查功能:首先将 MongoTemplate 注入到实体类中:做增、删、改、查功能时,直接使用即可。
@Component
public class UserRepositoryImpl implements UserRepository {

    @Autowired
    private MongoTemplate mongoTemplate;

}
  • 添加数据:
@Override
public void saveUser(UserEntity user) {
    mongoTemplate.save(user);
}
  • save 方法中会进行判断,如果对象包含了 ID 信息就会进行更新,如果没有包含 ID 信息就自动保存。
  • 根据用户名查询对象:
@Override
public User findUserByUserName(String userName) {
    Query query=new Query(Criteria.where("userName").is(userName));
    User user =  mongoTemplate.findOne(query , User.class);
    return user;
}
  • 更新对象比较灵活,可以选择更新一条数据,或者更新多条数据。
@Override
public long updateUser(User user) {
    Query query=new Query(Criteria.where("id").is(user.getId()));
    Update update= new Update().set("userName", user.getUserName()).set("passWord", user.getPassWord());
    //更新查询返回结果集的第一条
    UpdateResult result =mongoTemplate.updateFirst(query,update,User.class);
    //更新查询返回结果集的所有
    // mongoTemplate.updateMulti(query,update,UserEntity.class);
    if(result!=null)
        return result.getMatchedCount();
    else
        return 0;
}
  • 删除对象:
@Override
public void deleteUserById(Long id) {
    Query query=new Query(Criteria.where("id").is(id));
    mongoTemplate.remove(query,User.class);
}
  • (5)开发对应的测试方法
  • 测试时注入封装好的 UserRepository,根据情况调用对应的方法即可:
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTest {
    @Autowired
    private UserRepository userRepository;
}
  • 测试插入数据:
@Test
public void testSaveUser() throws Exception {
    User user=new User();
    user.setId(2l);
    user.setUserName("小明");
    user.setPassWord("fffooo123");
    userRepository.saveUser(user);
}
  • 测试查询方法:
@Test
public void findUserByUserName(){
    User user= userRepository.findUserByUserName("小明");
   System.out.println("user is "+user);
}
  • 测试更新
@Test
public void updateUser(){
    User user=new User();
    user.setId(2l);
    user.setUserName("天空");
    user.setPassWord("fffxxxx");
    userRepository.updateUser(user);
}
  • 最后测试删除
@Test
public void deleteUserById(){
    userRepository.deleteUserById(1L);
}
  • (6)查看验证结果
  • 可以使用工具 Robo 3T 来连接后直接图形化展示查看,也可以登录服务器用命令来查看。
  • a.登录 mongos:
bin/mongo -host localhost -port 20000
  • b.切换到 test 库:
use test
  • c.查询 userEntity 集合数据:
db.user.find()
  • 根据 c 查询的结果来观察测试用例的执行是否正确,到此 MongoTemplate 的增、删、改、查功能已经全部实现。

2、MongoRepository 的使用

MongoRepository 继承于 PagingAndSortingRepository,再往上就是 CrudRepository,根据下面的类图可以看出 MongoRepository 和前面 JPA、Elasticsearch 的使用比较类似,都是 Spring Data 家族的产品,最终使用方法也就和 JPA、ElasticSearch 的使用方式类似,可以根据方法名自动生成 SQL 来查询。

  • MongoRepository 项目结构和上面类似,只有 Repository 层的代码有所变化,如下:
public interface UserRepository extends MongoRepository<UserEntity, Long> {
    UserEntity findByUserName(String userName);
}
  • 我们新建 UserRepository 需要继承 MongoRepository,这样就可直接使用 MongoRepository 的内置方法。

  • 使用 UserRepository 进行增、删、改、查功能,首先将 UserRepository 注入到类中:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserDaoTest {
    @Autowired
    private UserRepository userRepository;
}
  • 集成 MongoRepository 会默认实现很多的内置方法,其中就包括保持、删除等操作。
  • 测试保存数据:
@Test
public void testSaveUser() throws Exception {
    User user=new User();
    user.setId(i);
    user.setUserName("小明"+i);
    user.setPassWord("fffooo123");
    userRepository.save(user);
}
  • 测试根据属性查询:
@Test
public void findUserByUserName(){
  User user= userRepository.findByUserName("小明");
   System.out.println("user is "+user);
}
  • 测试更新属性,保存和更新都使用的是 save() 方法,内部会根据实体是否有注解来判断是用来更新还是用来保存。
@Test
public void updateUser(){
    User user=new User();
    user.setId(2l);
    user.setUserName("天空");
    user.setPassWord("fffxxxx");
    userRepository.save(user);
}
  • 测试删除数据:
@Test
public void deleteUserById(){
    userRepository.delete(1l);
}
  • 我们发现 UserRepository 已经自动实现了常用的数据库操作,不用像使用 MongoTemplate 那样需要手动来实现。
  • 如果想使用分页怎么办?只需要在 UserRepository 再加入一个空方法,不需要自己实现。
Page<UserEntity> findAll(Pageable var1);
  • 首先使用 save 方法插入 100 个 UserEntity:
@Test
public void testSaveUser() throws Exception {
    for (long i=0;i<100;i++) {
        User user=new User();
        user.setId(i);
        user.setUserName("小明"+i);
        user.setPassWord("fffooo123");
        userRepository.save(user);
    }
}
  • 返回测试分页,设置以 ID 的倒叙排序,每页 10 条数据,取第二页的用户列表。
@Test
public void testPage(){
    Sort sort = new Sort(Sort.Direction.DESC, "id");
    Pageable pageable = PageRequest.of(2, 10, sort);
    Page page=userRepository.findAll(pageable);
    System.out.println("users: "+page.getContent().toString());
}
  • Pageable 是 Spring Data 库中定义的一个接口,该接口是所有分页相关信息的一个抽象,通过该接口,可以得到和分页相关所有信息(如 pageNumber、pageSize 等),这样,JPA 就能够通过 pageable 参数来得到一个带分页信息的 SQL 语句。
  • Page 类也是 Spring Data 提供的一个接口,该接口表示一部分数据的集合以及其相关的下一部分数据、数据总数等相关信息,通过该接口,可以得到数据的总体信息(数据总数、总页数...)以及当前数据的信息(当前数据的集合、当前页数等)。

在 Spring Boot 2.0 中 new PageRequest(2, 10, sort) 已经过期不再推荐使用,2.0 中推荐使用 PageRequest.of(2, 10, sort) 来做排序参数控制。

我们发现使用 Repository 的方式和前几课介绍的 Spring Boot JPA 非常相似,其实 spring-boot-starter-data-mongodb 和 Spring-boot-starter-data-jpa 都来自于 Spring Data 大家族,它们的实现原理基本一致,因此使用 Repository 完全可以参考前面课程 JPA 用法。

3、多数据源 MongoDB 的使用

  • 我们来学习在多数据源的情况下,如何使用 MongoDB。
  • (1)添加配置
  • 首先在配置文件中添加不同的数据源,配置文件添加两条数据源,如下:
mongodb.primary.uri=mongodb://192.168.0.1:27017
mongodb.primary.database=primary
mongodb.secondary.uri=mongodb://192.168.0.1:27017
mongodb.secondary.database=secondary
  • 如果使用的是 MongoDB 集群可以这样配置:
mongodb.xxx.uri=mongodb://192.168.0.1:27017,192.168.0.2:27017,192.168.0.3:27017
mongodb.xxx.database=xxx
  • (2)配置数据源

  • 封装读取以 MongoDB 开头的两个配置文件:

@Data
@ConfigurationProperties(prefix = "mongodb")
public class MultipleMongoProperties {

    private MongoProperties primary = new MongoProperties();
    private MongoProperties secondary = new MongoProperties();
    //省略 getter、setter
}
  • 创建 MultipleMongoConfig 类分别创建两个数据源的 MongoTemplate。
@Configuration
public class MultipleMongoConfig {
    @Autowired
    private MultipleMongoProperties mongoProperties;
}
  • 根据配置文件信息构建第一个数据源的 MongoDbFactory。
@Bean
@Primary
public MongoDbFactory primaryFactory(MongoProperties mongo) throws Exception {
    MongoClient client = new MongoClient(new MongoClientURI(mongoProperties.getPrimary().getUri()));
    return new SimpleMongoDbFactory(client, mongoProperties.getPrimary().getDatabase());
}
  • 利用上面构建好的 MongoDbFactory 创建对应的 MongoTemplate 。
@Primary
@Bean(name = "primaryMongoTemplate")
public MongoTemplate primaryMongoTemplate() throws Exception {
    return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary()));
}
  • 最后将 MongoTemplate 信息注入到对应的包路径下:
@Configuration
@EnableConfigurationProperties(MultipleMongoProperties.class)
@EnableMongoRepositories(basePackages = "com.neo.repository.primary",
        mongoTemplateRef = "primaryMongoTemplate")
public class PrimaryMongoConfig {
}

以上第一个数据源就配置完成了,第二个数据源的配置过程类似,大家可以直接看课程演示项目。总结一下封装过程:读取配置信息封装为 Properties,根据 Properties 信息构建 Factory,再由 Factory 构建出最后需要使用的 MongoTemplate,MongoTemplate 在根据包路径配置注入到对应的包下。

  • (3)创建两个库分别对应的对象和 Repository
public class User implements Serializable {
        private static final long serialVersionUID = -3258839839160856613L;
        private String  id;
        private String userName;
        private String passWord;
        //省略getter setter
}
  • 对应的 Repository:
public interface PrimaryRepository extends MongoRepository<User, String> {
}
  • 继承了 MongoRepository 会默认实现很多基本的增、删、改、查功能,省了很多自己写 Dao 层的代码,Secondary 和上面的代码类似就不贴出来了。

  • (4)最后测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class MuliDatabaseTest {
    @Autowired
    private PrimaryRepository primaryRepository;
    @Autowired
    private SecondaryRepository secondaryRepository;

    @Test
    public void TestSave() {
        this.primaryRepository.save(new User("小张", "123456"));
        this.secondaryRepository.save(new User("小王", "654321"));
        List<User> primaries = this.primaryRepository.findAll();
        for (User primary : primaries) {
            System.out.println(primary.toString());
        }
        List<User> secondaries = this.secondaryRepository.findAll();
        for (User secondary : secondaries) {
            System.out.println(secondary.toString());
        }
    }
}
  • 输出内容如下:
com.neo.entity.UserEntity@2a3a299[id=5a0ed2d7439f6618ac294ba6,userName=小张,passWord=123456]
com.neo.entity.UserEntity@5b989dc7[id=5a0ed2d7439f6618ac294ba7,userName=小王,passWord=654321]
  • 使用 Robo 3T 分别查看两个库的数据,均已经有对应的 User 对象,说明多数据源使用测试成功。

三、总结

两种方式都可以方便地操作 MongoDB 数据库,MongoTemplate 模式比较灵活可以根据自己的使用情况进行组装,MongoRepository 的使用方式更简单,因为继承了 Spring Data,所以默认实现了很多基础的增、删、改、查功能,业务直接拿来使用即可。简单日常的使用推荐 MongoRepository,简单方便利于项目快速开发,复杂多变的查询推荐使用 MongoTemplate 自行进行封装。

本文转载自:https://gitbook.cn/gitchat/column/5b86228ce15aa17d68b5b55a/topic/5c19099d1e59245d4d2ab843

zw965
粉丝 1
博文 49
码字总数 5811
作品 0
长沙
高级程序员
私信 提问
SpringBootBucket 1.0.0 发布,SprintBoot 全家桶

Spring Boot 现在已经成为Java 开发领域的一颗璀璨明珠,它本身是包容万象的,可以跟各种技术集成。 本项目对目前Web开发中常用的各个技术,通过和SpringBoot的集成,并且对各种技术通过“一...

一刀
2018/03/05
8.9K
17
Spring Boot 全家桶 - SpringBootBucket

Spring Boot 现在已经成为Java 开发领域的一颗璀璨明珠,它本身是包容万象的,可以跟各种技术集成。 本项目对目前Web开发中常用的各个技术,通过和SpringBoot的集成,并且对各种技术通过“一...

一刀
2018/03/05
11.4K
8
SpringBootBucket 2.0.4 发布,代号“傲娇的小二晶”

SpringBootBucket 自从1.0.0版本发布后就有好多人喜欢,目前码云上面star数量接近1.2k。上个月还收到了红薯签名的1000 star奖杯,这个我自己也觉得很惊讶。 由于SpringBoot 1.x官方将终止维护...

一刀
2018/09/16
2.8K
4
SpringBoot | 第三十一章:MongoDB的集成和使用

前言 上一章节,简单讲解了如何集成。本章节,我们来看看如何集成的。是最早热门非关系数据库的之一,使用也比较普遍。最适合来存储一些非结构数据了,适合对大量或者无固定格式的数据进行存...

oKong
2018/11/01
1K
2
JAVA springboot b2b2c多用户商城系统源码 (八)springboot整合mongodb

准备工作 安装 MongoDB jdk 1.8 maven 3.0 idea 环境依赖 在pom文件引入spring-boot-starter-data-mongodb依赖: 数据操作dao层 写一个接口,继承MongoRepository,这个接口有了几本的CURD的...

sccspuercode
03/15
109
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Boot WebFlux 增删改查完整实战 demo

03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello 。这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD WebFlux 应用,让开发更方便。这里...

泥瓦匠BYSocket
2分钟前
2
0
从0开始学FreeRTOS-(列表与列表项)-3

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
5分钟前
1
0
Java反射

Java 反射 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的 Class,Class 类 用于表示.class 文件(字节码)) 一、反射的概述 定义:JAVA 反射机制是在运行状态中,对于任...

zzz1122334
32分钟前
2
0
聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
5
0
前端技术之:webpack热模块替换(HMR)

第一步:安装HMR中间件: npm install --save-dev webpack-hot-middleware 第二步:webpack配置中引入webpack对象 const webpack = require('webpack’); 第三步:增加devServer配置项: ho......

popgis
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部