前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springboot实战之nosql整合(mongodb篇)

springboot实战之nosql整合(mongodb篇)

作者头像
lyb-geek
发布2019-10-08 11:55:34
3.5K0
发布2019-10-08 11:55:34
举报

什么是NoSQL?

NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。

NoSQL的优点/缺点

优点:

  • 高可扩展性
  • 分布式计算
  • 低成本
  • 架构的灵活性,半结构化数据
  • 没有复杂的关系

缺点:

  • 没有标准化
  • 有限的查询功能
  • 最终一致是不直观的程序

NoSQL适用场景

  • 数据模型比较简单
  • 需要灵活性更强的IT系统
  • 对数据库性能要求较高
  • 不需要高度的数据一致性
  • 对于给定key,比较容易映射复杂值的环境

NoSQL数据库分类

什么是mongodb

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

mongodb的特点

它的特点是高性能、易部署、易使用,存储数据非常方便。主要功能特性有:

  • 模式自由。
  • 支持动态查询。
  • 支持完全索引,包含内部对象。
  • 支持查询。
  • 支持复制和故障恢复。
  • 使用高效的二进制数据存储,包括大型对象(如视频等)。
  • 自动处理碎片,以支持云计算层次的扩展性。
  • 支持 Golang,RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。文件存储格式为BSON(一种JSON的扩展)。
  • 可通过网络访问。

mongodb适用场景

MongoDB 的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)和传统的RDBMS 系统(具有丰富的功能)之间架起一座桥梁,它集两者的优势于一身。

根据官方网站的描述,Mongo 适用于以下场景。

  • 网站数据:Mongo 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
  • 缓存:由于性能很高,Mongo 也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo 搭建的持久化缓存层可以避免下层的数据源过载。
  • 大尺寸、低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
  • 高伸缩性的场景:Mongo 非常适合由数十或数百台服务器组成的数据库,Mongo 的路线图中已经包含对MapReduce 引擎的内置支持。
  • 用于对象及JSON 数据的存储:Mongo 的BSON 数据格式非常适合文档化格式的存储及查询。

MongoDB 的使用也会有一些限制,例如,它不适合于以下几个地方。

  • 高度事务性的系统:例如,银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
  • 传统的商业智能应用:针对特定问题的BI 数据库会产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。
  • 需要SQL 的问题

mongodb概念解析

springboot与mongodb整合

该例子演示的功能有如下

  • mongodb 事务
  • mongodb 自增ID
  • mongodb 字段驼峰和mongdb属性下划线映射
  • mongodb 自定义转换器实现
  • mongodb 分页

1、mongodb事务

具体实现可查看之前的文章springboot实战之mongodb事务支持

2、mongodb 自增ID

其核心主要是重写AbstractMongoEventListener,这个类可以监听MongoDB的生命周期。其监听回调的方法如下

核心代码

@Componentpublic class GeneratedValueMongodbEventListener extends AbstractMongoEventListener<Object> {
  @Autowired  private MongoTemplate mongoTemplate;
  /**   * 调用MongoTemplate的insert、insertList和save操作,在通过MongoConverter将对象转换为文档之前的处理。   * @param event   */  @Override  public void onBeforeConvert(BeforeConvertEvent<Object> event) {
    Object source = event.getSource();    if(source != null) {      ReflectionUtils.doWithFields(source.getClass(), field -> {        ReflectionUtils.makeAccessible(field);        if (field.isAnnotationPresent(GeneratedValue.class)) {          //设置自增ID          boolean hasDocumentAnnotation = source.getClass().isAnnotationPresent(Document.class);          String collectionName = source.getClass().getSimpleName();          if(hasDocumentAnnotation){            Document document = source.getClass().getAnnotation(Document.class);            collectionName = document.value();          }
          field.set(source, getNextId(collectionName));        }      });    }  }
 /**   * 获取下一个自增ID   * @param collName  集合名   * @return   */  private Long getNextId(String collName) {    Query query = new Query(Criteria.where("collName").is(collName));    Update update = new Update();    update.inc("seqId", 1);    FindAndModifyOptions options = new FindAndModifyOptions();    options.upsert(true);    options.returnNew(true);    SequenceId seqId = mongoTemplate.findAndModify(query, update, options, SequenceId.class);    return seqId.getSeqId();  }

具体完整代码可以查看如下链接

http://1t.click/ajgz

3、mongodb 字段驼峰和mongdb属性下划线映射

通过重写org.springframework.data.mapping.model.FieldNamingStrategy来实现,其代码如下

//参考FieldNamingStrategy的其他实现//userName->user_namepublic class CamelCaseFieldNamingStrategy implements FieldNamingStrategy {    @Override    public String getFieldName(PersistentProperty<?> property) {        List<String> parts = ParsingUtils.splitCamelCaseToLower(property.getName());        StringBuilder sb = new StringBuilder();        Iterator it = parts.iterator();        if(it.hasNext()){            sb.append(it.next().toString());            while (it.hasNext()){                sb.append("_");                sb.append(it.next().toString());            }        }        return sb.toString();    }}

要使其字段命名策略生效,还需得更改mongodb默认的字段命名策略规则,其更换代码如下

 @Bean  public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context, BeanFactory beanFactory) {    DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);    MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);    // Don't save _class to mongo    mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));    if("SNAKE_CASE".equalsIgnoreCase(fieldNamingStrategy)) {      context.setFieldNamingStrategy(new CamelCaseFieldNamingStrategy());    }
    return mappingConverter;  }

4、mongodb 自定义转换器实现

通过实现org.springframework.core.convert.converter.Converter接口,其例子代码如下

// Direction: MongoDB -> Java@ReadingConverterpublic class GenderReadConverter implements Converter<Integer, Gender> {
  @Override  public Gender convert(Integer integer) {
    return Gender.getValue(integer);  }}
// Direction: Java -> MongoDB@WritingConverterpublic class GenderWriteConverter implements Converter<Gender,Integer> {
  @Override  public Integer convert(Gender gender) {
    return gender.getValue();  }}

要使其转换规则生效,还需做如下配置

 @Bean  public MongoCustomConversions mongoCustomConversions() {    return new MongoCustomConversions(Arrays.asList(new GenderWriteConverter(),new GenderReadConverter()));  }
 @Bean  public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context, BeanFactory beanFactory) {    DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);    MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);    // Don't save _class to mongo    mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));    mappingConverter.setCustomConversions(mongoCustomConversions());
    return mappingConverter;  }

5、mongodb 分页

其分页主要拿Ryan Miao这位博主在github上已经实现的代码,不过该代码在带查询条件分页时,会有bug,我这边做了调整,然后这位博主针对分页,也写了一篇文章,其链接如下,感兴趣的朋友可以看下

https://www.cnblogs.com/woshimrf/p/mongodb-pagenation-performance.html

总结

springboot与mongodb的整合就写这么多了,nosql其含义不是no sql,并不是为了来取代传统关系型数据库,而是not only sql,是作为传统关系型数据库的补充,因为在某些业务场景下,nosql是无法满足业务要求的,比如强事务要求场景

参考文档

https://www.runoob.com/mongodb/nosql.html https://baike.baidu.com/item/mongodb https://baike.baidu.com/item/NoSQL

MONGO 生命周期

https://www.cnblogs.com/vana/p/10860106.html

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-mongodb

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linyb极客之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • NoSQL的优点/缺点
  • NoSQL适用场景
  • NoSQL数据库分类
  • 什么是mongodb
  • mongodb的特点
  • mongodb适用场景
  • mongodb概念解析
  • springboot与mongodb整合
  • 总结
  • 参考文档
  • demo链接
相关产品与服务
云数据库 MongoDB
腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档