SpringBoot集成MongoDB-Spring专区论坛-技术-SpringForAll社区

SpringBoot集成MongoDB

[toc]

NoSql

NotOnly Sql,不仅仅是 sql 。

NoSql数据库分类:     键值对:redis     列存储:Hbase     文档型:mongodb     图形(graph)数据库:Neo4j,infogrid

MongoDB

是一个基于分布式文件存储的数据库,c++编写,可扩展高性能数据存储方案。MongoDb介于关系型数据库和非关系型数据库之间,是非关系型数据库中功能最多的,最像关系型数据库。数据结构非常松散可以存储非常复杂的数据对象。Mongodb支持的查询语言非常强大,语法类似于面向对象的查询语言,几乎可以实现类似关系型数据库单表查询的所有功能,而且还支持对数据建立索引。

在高负载的情况下,MongoDB 天然支持水平扩展和高可用,可以很方便地添加节点/实例,以保证服务性能和可用性。MongoDB 可以用于代替传统的关系型数据库或键/值存储方式,皆在为 Web 应用提供可扩展的高可用高性能数据存储解决方案。

存储结构

  • 文档(Document) :MongoDB 中最基本的单元,由 BSON 键值对(key-value)组成

  • 集合(Collection) :一个集合可以包含多个文档,每个文档的结构可以不同

  • 数据库(Database) :一个数据库中可以包含多个集合,可以在 MongoDB 中创建多个数据库

BSON是 Binary JSON的简称,是 JSON 文档的二进制表示,支持将文档和数组嵌入到其他文档和数组中,还包含允许表示不属于 JSON 规范的数据类型的扩展。与 JSON 相比,BSON 着眼于提高存储和扫描效率

传统关系型数据和MongoDB类比:

MongoDB 传统关系型数据库
Database schema
Collection Table
Document Row
Field Column

特性

  • BSON:MongoDB 中的数据就是一个 BSON 文档,它是由键值对组成的数据结构,类似于 JSON 对象,是 MongoDB 中的基本数据单元
  • 模式自由:集合的概念类似 MySQL 里的表,但它不需要定义任何模式,能够用更少的数据对象表现复杂的领域模型对象
  • 支持多种查询方式 :MongoDB 查询 API 支持读写操作 (CRUD)以及数据聚合、文本搜索和地理空间查询。
  • 支持 ACID 事务 :NoSQL 数据库通常不支持事务,为了可扩展和高性能进行了权衡。不过,也有例外,MongoDB 就支持事务。与关系型数据库一样,MongoDB 事务同样具有 ACID 特性。MongoDB 单文档原生支持原子性,也具备事务的特性。MongoDB 4.0 加入了对多文档事务的支持,但只支持复制集部署模式下的事务,也就是说事务的作用域限制为一个副本集内。MongoDB 4.2 引入了分布式事务,增加了对分片集群上多文档事务的支持,并合并了对副本集上多文档事务的现有支持。
  • 聚合管道:聚合管道用来执行数据聚合、过滤的操作
  • 支持多种类型的索引 :单字段索引、复合索引、多键索引、哈希索引、文本索引、 地理位置索引等
  • 支持 failover :提供自动故障恢复的功能,主节点发生故障时,自动从从节点中选举出一个新的主节点,确保集群的正常使用,这对于客户端来说是无感知的
  • 支持分片集群 :MongoDB 支持集群自动切分数据,让集群存储更多的数据,具备更强的性能。在数据插入和更新时,能够自动路由和存储。
  • 支持存储大文件 :MongoDB 的单文档存储空间要求不超过 16MB。对于超过 16MB 的大文件,MongoDB 提供了 GridFS 来进行存储,通过 GridFS,可以将大型数据进行分块处理,然后将这些切分后的小文档保存在数据库中。

实践

pom


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

yml


spring:
  application:
    name: MongoApp
  data:
    mongodb:
      uri: mongodb://127.0.0.1:27017/FirstMongoDBSchema



logging:
  level:
    org.springframework.data.mongodb: debug

model


package com.ramble.mongodb.model;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
import java.util.Date;

@Data
@Document(collection = "students")
public class Student implements Serializable {

    @Id
    private Long id;
    private String userName;
    private String passWord;
    private Integer age;
    private Date createTime;
}

  • Document:此实体对应的文档
  • collection=”students”:此实体所属的集合为students集合
  • Id:文档的id,唯一标识

repository


package com.ramble.mongodb.repository;
import com.ramble.mongodb.model.Student;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends MongoRepository<Student, Integer> {

List<Student> findByUserName(String userName);

List<Student> findByPassWordLike(String passWord);

@Query(   value = "{'age' : {\"$gt\" : ?0}}")List<Student> findList(Integer age);

}

  • MongoRepository:继承MongoRepository即可开箱即用基本的CURD操作 图片[1]-SpringBoot集成MongoDB-Spring专区论坛-技术-SpringForAll社区
  • Query: 如果默认的无法满足需求,可以编写自定义查询语句
  • findList:表示查询age 大于 传递进来的age参数的数据,?0 表示获取参数列表的第一个参数,这里就体现框架的强大之处了,这里的写法非常类似 spring-data-jpa 的写法。框架屏蔽了技术实现的细节,用过jpa的开发人员可以很平滑的在项目中继承mongodb。
  • findByUserName: 查询userName等于传递进来的userName参数的数据,会自动生成查询语句,可通过控制台输出观察到

controller



package com.ramble.mongodb.controller;
import com.alibaba.fastjson.JSON;
import com.ramble.mongodb.model.Student;
import com.ramble.mongodb.repository.StudentRepository;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;

@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/student")
public class StudentController {

    private StudentRepository studentRepository;
    
    @PostMapping("/")
    public void create(@RequestBody Student param) {
        Student save = studentRepository.save(param);
    }
    
    @DeleteMapping("/{id}")
    public void delete(@PathVariable Integer id) {
        studentRepository.deleteById(id);
    }
    
    @PutMapping("/")
    public Student update(@RequestBody Student param) {
        Student save = studentRepository.save(param);
        return save;
    }
    
    @GetMapping("/{id}")
    public Student get(@PathVariable Integer id) {
        Optional<Student> byId = studentRepository.findById(id);
        return byId.get();
    }
    
    @GetMapping("/")
    public List<Student> find() {
        List<Student> all = studentRepository.findAll();
        return all;
    }
    
    @GetMapping("/biz")
    public void findBiz() {
        List<Student> c = studentRepository.findByUserName("string");
        log.info("查询结果为:" + JSON.toJSONString(c));
        List<Student> like = studentRepository.findByPassWordLike("123");
        log.info("查询结果为:" + JSON.toJSONString(like));
        List<Student> list = studentRepository.findList(9);
        log.info("查询结果为:" + JSON.toJSONString(list));
    }
    
    
}

findBiz 接口打印的日志为:



2023-07-18 14:21:46.105 DEBUG 29044 --- [nio-8080-exec-3] o.s.d.m.r.query.MongoQueryCreator        : Created query Query: { "userName" : "string"}, Fields: {}, Sort: {}
2023-07-18 14:21:46.106 DEBUG 29044 --- [nio-8080-exec-3] o.s.data.mongodb.core.MongoTemplate      : find using query: { "userName" : "string"} fields: Document{{}} for class: class com.ramble.mongodb.model.Student in collection: students
2023-07-18 14:21:46.110  INFO 29044 --- [nio-8080-exec-3] c.r.m.controller.StudentController       : 查询结果为:[{"age":0,"createTime":1689657852733,"id":222,"passWord":"string","userName":"string"},{"age":0,"createTime":1689657852733,"id":333,"passWord":"string","userName":"string"}]
2023-07-18 14:21:46.111 DEBUG 29044 --- [nio-8080-exec-3] o.s.d.m.r.query.MongoQueryCreator        : Created query Query: { "passWord" : { "$regularExpression" : { "pattern" : "123", "options" : ""}}}, Fields: {}, Sort: {}
2023-07-18 14:21:46.112 DEBUG 29044 --- [nio-8080-exec-3] o.s.data.mongodb.core.MongoTemplate      : find using query: { "passWord" : { "$regularExpression" : { "pattern" : "123", "options" : ""}}} fields: Document{{}} for class: class com.ramble.mongodb.model.Student in collection: students
2023-07-18 14:21:46.114  INFO 29044 --- [nio-8080-exec-3] c.r.m.controller.StudentController       : 查询结果为:[{"age":20,"createTime":1689659233455,"id":202,"passWord":"123456","userName":"cr8"}]
2023-07-18 14:21:46.115 DEBUG 29044 --- [nio-8080-exec-3] o.s.d.m.r.query.StringBasedMongoQuery    : Created query Document{{age=Document{{$gt=9}}}} for Document{{}} fields.
2023-07-18 14:21:46.115 DEBUG 29044 --- [nio-8080-exec-3] o.s.data.mongodb.core.MongoTemplate      : find using query: { "age" : { "$gt" : 9}} fields: Document{{}} for class: class com.ramble.mongodb.model.Student in collection: students
2023-07-18 14:21:46.117  INFO 29044 --- [nio-8080-exec-3] c.r.m.controller.StudentController       : 查询结果为:[{"age":100,"createTime":1689659233455,"id":22,"passWord":"string","userName":"c8"},{"age":20,"createTime":1689659233455,"id":232,"passWord":"string","userName":"cr8"},{"age":20,"createTime":1689659233455,"id":202,"passWord":"123456","userName":"cr8"}]

通过log可以观察到 MongoRepository 自动生成的查询语句以及 Query 方法生成的查询语句

MongoTemplate

除了 MongoRepository ,MongoTemplate 也可以用来访问 mongodb ,这种方式更加原始,需要开发人员编写的代码更多,但同时它的可自定义程度更高,可以用来编写复杂的查询语句。



package com.ramble.mongodb.repository;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.ramble.mongodb.model.FirstMongoDBSchemeCollection;
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.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.List;

@Repository
public class FirstMongoDBSchemeCollectionRepositoryImpl implements FirstMongoDBSchemeCollectionRepository {

    @Resource
    private MongoTemplate mongoTemplate;
    
    public void insert(FirstMongoDBSchemeCollection model) {
        FirstMongoDBSchemeCollection insertResult = mongoTemplate.insert(model);
    }
    
    @Override
    public void save(FirstMongoDBSchemeCollection model) {
        FirstMongoDBSchemeCollection saveResult = mongoTemplate.save(model);
    }
    
    @Override
    public void remove(FirstMongoDBSchemeCollection model) {
        DeleteResult deleteResult = mongoTemplate.remove(model);
        //mongoTemplate.remove
    }
    
    @Override
    public void update(FirstMongoDBSchemeCollection model) {
        Query query = new Query(Criteria.where("id").is(model.getId()));
        Update update = new Update();
        update.set("name", model.getName());
        update.set("age", model.getAge());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, FirstMongoDBSchemeCollection.class);
    }
    
    @Override
    public FirstMongoDBSchemeCollection findById(String id) {
        Query query = new Query(Criteria.where("id").is(id));
        FirstMongoDBSchemeCollection model = mongoTemplate.findById(id, FirstMongoDBSchemeCollection.class);
        return model;
    }
    
    @Override
    public FirstMongoDBSchemeCollection findOne(FirstMongoDBSchemeCollection model) {
        Query query = new Query();
        FirstMongoDBSchemeCollection findResult = mongoTemplate.findOne(query, FirstMongoDBSchemeCollection.class);
        return findResult;
    }
    
    @Override
    public List<FirstMongoDBSchemeCollection> findList() {
        Query query = new Query();
        List<FirstMongoDBSchemeCollection> firstMongoDBSchemeCollections = mongoTemplate.find(query, FirstMongoDBSchemeCollection.class);
        return firstMongoDBSchemeCollections;
    }
}


引用

请登录后发表评论

    没有回复内容