热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringData与MongoDB:不协调的设计

MongoDB是一款非常知名的NoSQL文档数据库,而Spring则是Java领域著名的开源框架。除了构成Spring核心的IoC与AOP之外,Spring也有大量应用于各个不同领域的子框架,其中SpringData就是专门针对数据处理的一个子项目。在SpringData下有SpringDataJPA、Sprin

  MongoDB是一款非常知名的NoSQL文档数据库,而Spring则是Java领域著名的开源框架。除了构成Spring核心的IoC与AOP之外,Spring也有大量应用于各个不同领域的子框架,其中Spring Data就是专门针对数据处理的一个子项目。在Spring Data下有Spring Data JPA、Spring Data MongoDB、Spring Data Redis等子项目,从名字就可以看出来这些子项目所针对的目标。其中,Spring Data MongoDB是专门针对MongoDB的一个子项目,旨在通过Spring的方式来操纵MongoDB,那么这种集成是简化了开发还是阻碍了开发呢?

  Prashant Deva是Chronon的创始人与CTO。他是一位持续创业者,还创办了Placid Systems、AntlrStudio及Virtual Ant。作为一名极客,Deva喜欢尝试各种新鲜技术,在使用了Spring Data MongoDB一段时间后,他认为这个框架在设计上存在着严重的问题,并撰写了文章进行了深入且详尽的分析。

Spring框架开发者们喜欢到处宣扬他们对MongoDB提供的支持,并以此作为优于其他框架的一个资本。不过,如果在真正的项目中使用Spring
Data MongoDB的话,你就会发现框架在某些特性上的严重缺失以及设计上的巨大失误。

  Spring Data MongoDB试图将ORM风格的架构硬塞到非关系型数据库中,这直接造成在实际项目中根本无法使用的严重后果,下面就来谈谈这背后的原因:

无法检索字段,只能获取整个文档

  这是Spring Data MongoDB设计上最大的瑕疵。它试图用SQL数据库中的行对文档进行建模,并且希望你像ORM一样创建“实体”类。这两者根本就不是一回事。文档可要比SQL数据库中的行复杂多了,也大多了。

  对于SQL数据库中的行来说,它认为你在大多数查询中都会获取到里面的所有数据,否则数据就应该被划分到多张表中。不过文档与之完全不同,文档可以嵌套,很多时候你只想从数据库中获取到文档的一个子集而已。

  但对于Spring Data MongoDB的“实体”模型来说,你不得不在每次查询中都检索出整个文档才行。

没有DBRef延迟加载

  这个就更加疯狂了。如果通过DBRefs来引用其他文档,那么Spring Data MongoDB就会得到整个文档而不是文档引用。如果通过DBRefs连接了大量文档,那么一个只想获得几个字段的简单查询都会导致获取到整个文档图!

  实际情况是这个Bug报告已经有将近两年时间了,被指定为“低优先级”状态,也没有什么解决方案,这太让人难以置信了,这表明Spring Data MongoDB的愿景与实际的使用之间存在着多么大的差距。

不支持游标

  想要通过游标遍历集合吗?没门。要么就取出整个集合,要么就转而使用原生的Mongo Java驱动。

不完备的聚合框架支持

  Spring Data MongoDB是从不久之前才开始支持MongoDB聚合框架的,就像框架的其他部分一样,这种支持也是个半成品。

  框架文档很少并且容易让人产生混乱,在实际项目中所需的大多数聚合查询都没法在Spring Data MongoDB的文档中找到,你只能使用原生的驱动才行。

不完善的索引支持

  虽然可以通过框架将某个字段标记为“加索引的”,但其他操作却根本就不知道这回事。

  就拿MongoDB中的一个例子来说吧,如果某个字段是唯一且稀疏的,那么你就不能使用“null”值向文档中插入一次以上。这意味着在第2次插入时,该字段就不应该在第1次插入的位置处出现。

  然而,由于Spring强迫你在一个类中定义文档的字段,因此最后需要将null赋给不存在的字段。如果该字段拥有唯一的稀疏索引,那么这会导致运行期错误,因为Spring在根据实体对象创建查询时(以注解的形式直接定义在字段上),它根本就不知道索引的存在。

  Spring还提供了一个ensureIndex()方法用于手工在字段上创建索引,无需使用注解,不过文档中并没有提及何时该使用这种方式、使用的频率是多少,以及调用的性能是怎样的。

无法切换数据库

  很多时候,你希望将数据存储在单个MongoDB实例的不同数据库中,比如说要保持不同客户数据的分离。

  如果使用原生的Mongo驱动,那么切换数据库简直就是小菜一碟,直接调用getDb(dbName)就行了。但如果使用Spring Data MongoDb,那么这几乎是一件无法做到的事情,除非你愿意自己写大量的代码(不过这么做的话在新版框架发布后可能就会出现移植性问题)。

让人奇怪的日志框架

  我已经就Spring的文档问题专门写过一篇文章。Spring文档说它使用的是Jakarta Commons Logging,不过Spring Data显然使用的是SLF4J。然而,Spring Data文档却压根儿就没有提过这事。

  这意味着如果开始使用Spring Data,那么你可能就会遇到很多文档中没有提及的运行期错误,这时没别的办法,上StackOverflow上找答案吧。

不支持文档的动态特性

  使用MongoDB这样的面向文档的数据库最大的原因就在于其动态特性了。比如说同一集合中的文档可以不同,这样同一个集合中就可以有多个版本的文档,然后逐渐升级,文档也可以嵌套。键名不必事先知道,这样就可以直接向文档中插入属性映射。

  但事实却是Spring Data MongoDB丢弃了MongoDB的这个最基本的特性,并且试图在其上构建一个确定的、预先定义好的ORM风格的层,这直接造成框架与底层数据库之间的不匹配。

结论

  Spring Data MongoDB似乎是由一些压根儿就没有在真正的项目中用过MongoDB的人设计出来的,它试图将面向文档的数据库硬塞到ORM风格的框架中。

  这导致了框架与数据库之间的不匹配,Spring Data MongoDB反而成为了一个负担而不是帮助我们简化开发。最后,你还是不得不在几乎所有真正的项目开发中使用原生的MongoDB Java驱动。

后记

  各位InfoQ读者,你曾经使用过Spring Data MongoDB进行过MongoDB开发么,你对于Spring Data MongoDB的使用感受是如何呢?是否与Deva的经历一致呢?我曾经在项目中尝试过Spring Data MongoDB,使用下来的一个直观感受就是它将简单的事情搞复杂了。直接使用原生Java驱动来操纵MongoDB是个非常简单且直观的过程,而Spring Data MongoDB却沿用了它一直以来的处理风格,那就是IoC,需要先进行注入,然后从容器中获取所需的对象,将原本很轻松的操作变得复杂起来,不知各位读者有什么样的感受呢,欢迎讨论。

来自infoq


推荐阅读
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 本文介绍了数据库体系的基础知识,涵盖关系型数据库(如MySQL)和非关系型数据库(如MongoDB)的基本操作及高级功能。通过三个阶段的学习路径——基础、优化和部署,帮助读者全面掌握数据库的使用和管理。 ... [详细]
  • 58同城的Elasticsearch应用与平台构建实践
    本文由58同城高级架构师于伯伟分享,由陈树昌编辑整理,内容源自DataFunTalk。文章探讨了Elasticsearch作为分布式搜索和分析引擎的应用,特别是在58同城的实施案例,包括集群优化、典型应用实例及自动化平台建设等方面。 ... [详细]
  • 本文深入探讨了分布式文件系统的核心概念及其在现代数据存储解决方案中的应用,特别是针对大规模数据处理的需求。文章不仅介绍了多种流行的分布式文件系统和NoSQL数据库,还提供了选择合适系统的指导原则。 ... [详细]
  • Redis:缓存与内存数据库详解
    本文介绍了数据库的基本分类,重点探讨了关系型与非关系型数据库的区别,并详细解析了Redis作为非关系型数据库的特点、工作模式、优点及持久化机制。 ... [详细]
  • MongoDB核心概念详解
    本文介绍了NoSQL数据库的概念及其应用场景,重点解析了MongoDB的基本特性、数据结构以及常用操作。MongoDB是一个高性能、高可用且易于扩展的文档数据库系统。 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • MySQL缓存机制深度解析
    本文详细探讨了MySQL的缓存机制,包括主从复制、读写分离以及缓存同步策略等内容。通过理解这些概念和技术,读者可以更好地优化数据库性能。 ... [详细]
  • 科研单位信息系统中的DevOps实践与优化
    本文探讨了某科研单位通过引入云原生平台实现DevOps开发和运维一体化,显著提升了项目交付效率和产品质量。详细介绍了如何在实际项目中应用DevOps理念,解决了传统开发模式下的诸多痛点。 ... [详细]
  • 优化Flask应用的并发处理:解决Mysql连接过多问题
    本文探讨了在Flask应用中通过优化后端架构来应对高并发请求,特别是针对Mysql 'too many connections' 错误的解决方案。我们将介绍如何利用Redis缓存、Gunicorn多进程和Celery异步任务队列来提升系统的性能和稳定性。 ... [详细]
  • 本文介绍了一个基于 Java SpringMVC 和 SSM 框架的综合系统,涵盖了操作日志记录、文件管理、头像编辑、权限控制、以及多种技术集成如 Shiro、Redis 等,旨在提供一个高效且功能丰富的开发平台。 ... [详细]
  • 使用 Docker 部署 MongoDB 并通过 IntelliJ IDEA 远程访问
    本文详细介绍了如何使用 Docker 部署 MongoDB,并通过 IntelliJ IDEA 实现远程连接的方法。包括 MongoDB 的基本配置、用户管理以及如何在 IDE 中配置连接。 ... [详细]
  • 一家位于长沙的知名网络安全企业,现面向全国诚聘高级后端开发工程师,特别欢迎具有一线城市经验的技术精英回归故乡,共创辉煌。 ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • Oracle字符集详解:图表解析与中文乱码解决方案
    本文详细解析了 Oracle 数据库中的字符集机制,通过图表展示了不同字符集之间的转换过程,并针对中文乱码问题提供了有效的解决方案。文章深入探讨了字符集配置、数据迁移和兼容性问题,为数据库管理员和开发人员提供了实用的参考和指导。 ... [详细]
author-avatar
武艺最新单曲问月008
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有