• 1
  • 2
  • 3
  • 4
  • 5
mysql数据库问题 首 页  »  帮助中心  »  数据库  »  mysql数据库问题
MongoDB JVM开发库的介绍
发布日期:2016-4-26 22:4:41

  当存储基于文档的 JSON 数据的时候,MongoDB 是我最喜欢的数据库。 MongoDB 交互上基于 JVM 的语言在与有很多种选择。我觉得拿4个最流行的解决方案且都实现一个用例,对我来说不失为一个好的练习。示例:创建一个可获取一个城市与距其最近的城市的列表的 REST 服务。

  在本文我要比较的四个选择是:

  •   标准的MongoDB Java Driver
  •   Jongo
  •   Monphia
  •   Spring Data Mongo。

  为了简洁,我是用 groovy 完成代码,并使用 Spring Boot 以减少样板代码。

  一、基础配置

  Spring Boot 应用的代码非常简洁,参考代码如下所示:


  图1

  同时也提供了这次对比所使用的Gradle构建文件,代码如下所示:


  图2

  因为我使用了 Spring Boot 与 Spring Data MongoDB 框架,一些配置可忽略。比如,Spring Boot 框架在为 Spring Boot 的应用程序上下文提供了 MongoClient bean 与MongoTemplate bean。无需在你的配置文件中进行额外配置(我是用的是 YAML 风格的配置)。如图3所示的代码:


  图3

  基本框架完成之后,我们就可以开始对比。

  二、MongoDB Java驱动

  由于所有的连接 MongoDB 的程序,都用到了 MongoDB 原生的 Java 驱动,因此我觉得从 MongoDB Java Driver (下称 Java Driver)开始最合适。Java Driver 是 JVM 上使用 MongoDB 的最底层的途径。那即是说,写出的程序会略显冗长,且API不如其他的更加用户友好。但是,你使用Java Driver能够实现所有的功能。 在 Spring Data MongoDB 里Java Driver已经自动引入,若你需要单独使用的话,需要引入相应的依赖。

  下面是使用Java Driver实现的代码,如图4所示:


  图4

  Java Driver 整体是以 DBObject 为中心,需要一直提供领域对象与DBObject之间的映射。Java Driver没有提供任何形式的对象映射。值得幸运的是, DBObject 的结构很像 map,且 Groovy Map 的简洁的风格让其操作起来方便许多。本例中,要找到距某城市最近的城市以及其最短距离时,就需要用到 geoNear 命令,你可能需要从 mongoDB 的手册找到其详细的语法。语法缩略如图5所示:


  图5

  geoNear 命令会返回集合中距离最近的对象,并且提供一个字段来标识他们之间的距离;距离的单位是米。 geoNear 命令中的near字段的格式有两种:

  •   一种是上面代码示例
  •   一种是更传统的2个 double 值组成的数组。

  因为前一种符合 GeoJSON 的标准,我更推荐这种方式。当然你也可以用其他如mysql的方式。在我所示的例子中,我尽量都是用 GeoJSON 记法来存储地理位置信息数据。从代码里能看出来,我使用了一个提供了所有 GeoJSON 类型支持的 Java 类库。

  撇开所有 DBObject 到领域对象的约定,例子中所示的代码都非常易读。当然你需要知道 MongoDB 查询的细节;但当你了解了之后,Java Driver 是一个非常强大的工具。

  三、Jongo

  Jongo 框架支持基于字符串的交互与查询(查询时不需要创建 DBObject ),因此允许你使用接近于 Mongo Shell 的方式与 MongoDB 实例进行交互。Jongo 使用 Jackson 框架来完成对象映射,因此无需将查询结果与想插入的数据转换为 DBObject 实例。我在使用的 GeoJSON 库内置了Jackson 的支持,对此,我们无需为此多编写代码。

  Jongo的用例的代码如下所示:


  图6

  从图6所示的例子中可以看出,Jongo 更面向字符串,尤其是使用 GeoNear 命令查询的时候。同时,多亏 Jackson 框架,我们查询与插入时,不用编写任何的转换的代码。

  若你是先接触到MongoDB,熟悉shell命令并且不想做手工映射的话,Jongo是非常便捷的。但是,你需要去了解Mongo Shell API的确切语法;同时,你在构造查询、编写命令式没有自动的代码补全,如果你觉得这样是可以接受的话,Jongo是一个不错的选择。

  四、Morphia

  MongoDB 的开发者为MongoDB量身定做了一个映射框架。 Morphia是一个注解驱动的框架,那即是说为了使用 Morphia ,你得使用注解来注释你的 POJO (尽管如此,你可以不写注解以使用默认的注解)。 Morphia 支持 MongoDB 的大部分函数,令人遗憾的是,没有对 GeoJSON 提供支持从而也不支持 geoNear。MongoDB 的开发者专注的开发 MongoDB Java Driver 3.0,有些忽略 Morphia。 可能会在未来的版本中提供对 GeoJSON 的支持。

  由于我用到了 geoNear 函数,除把Java Driver的测试用例中的代码中的拿来复用也没有更好的选项了。如图7所示的是用 Morphia 实现的用例:


  图7

  因为 Morphia 框架没有对 GeoJSON 提供支持,所以,你要么使用传统的用包含两个坐标的 double 类型的数组,要么写你自己的转换器。我选择了后者,毕竟也不是那么难写。不要忘了把你的转换器加入到 Morphia 中。从上面所示的代码中可以看出,我已经使用 Morphia 的注解注释了 City 类,对于那些熟悉 JPA 的开发者来说,这种方式直截了当。同时,由于 Morphia 不提供 2dsphere index 查询支持,你要自己创建 2dsphere 索引。

  四、针对MongoDB的Spring Data

  最后但同样重要的是 Spring Data,我在研究如何用它完成这个用例。若你熟知 Spring Data 框架的话,你需要写与数据存储交互的库接口,使用方法名来指定你需要使用的查询。在此例中,我们只需要两个查询:根据名字查询城市,找到距某城市最近的城市。Spring Data 框架支持 geospatial 查询(地理空间查询)。

  Spring Data 框架有用来表示地理空间坐标的类,但与 GeoJSON 不兼容(再提一遍:Spring 有其自有的方式)。所幸 Spring Data 能够自动生成索引并且 mongo 也能够处理 Spring Data 使用的坐标表示方式。

  这是针对Morphia的实现:(译注:我认为是原文错误)如图8所示的代码:


  图8

  就可读性来说,Spring Data 无疑是最好的。你不需要知道 MongoDB 里的查询语句是怎么构建的,只需要使用库中的命名惯例就好。当你使用2dsphere 索引的时候,要记住的一点,就是使用 near query 方法时要加入 distance 参数,不然 Spring Data 在查询 MongoDB 时会忽略 sphere 选项(在此情况下会失败?报错)。若你不需要距离,你可以把命令的返回值城市对象的列表。你不用实现相应的接口,Spring Data 框架会替你实现。

  使用Spring Data MongoDB 框架的时候,你也可以使用 MongoTemplate 类。MongoTemplate 类提供了一种类似于 Jongo 和 Java Driver 的机制。使用 MongoTemplate 可以很容易的实现geoNear 查询。

  你也可能已经注意到,Spring Data MongoDB 是唯一一个没有在Java代码中提供数据库名字的框架。这是由于Spring Data使用MongoTemplate,而 MongoTemplate 需要你在配置文件中配置。也就是说,可将数据库的名字注入到对应的变量上,且使用此变量来代表数据库的名字。

  对于Spring Data Mongo唯一不满意的地方就是他们选取了一种不标准的方式来表示地理信息数据。如果你有一个mongo的集合,集合里全是使用GeoJSON格式化过的数据,由于仓库不能处理,基本上你就“完蛋”了(至少生成的near查询不行)。我尝试了在我映射的City对象里使用GeoJSON的类,但是不能使转换正常工作(Spring Data框架没有使用Jackson框架做序列化)。并且,库接口里的geoNear方法生成的query串使用的旧的坐标对,而不是GeoJSON几何结构。如果Spring Data能够提供对GeoJSON格式的位置和查询的支持,就像在一个很好的蛋糕顶端添加了一颗樱桃。

  五、结论

  对于这个用例,我对于框架选择是:Spring Data,接着就是Jongo与Java Driver。 Jongo排第二是由于其映射的功能,而不是其他方面的功能;Java Driver也基本相同。Morphia排最后是由于缺少对geoNear查询的支持,并缺少对地理对象的内置支持(double类型的数组除外)。当Morphia的下一个版本发布的时候,它的关注点可能会改变。使用Java Driver写出的程序可能较冗长,但与Groovy搭配在一起使用,冗长的缺点也可以克服。

  这是一个相当简单的例子,但对我来说这是一个宝贵的学习经验。基于上文中我的了解,我可能倾向于使用Spring Data MongoDB框架,并当在库接口里函数过于复杂时,我会引入Java Driver。或许在其他的场景下,我的选择会不一样,也有可能选择mysql或者其他的,时间会给我答案。我觉得,胸中有了这两个的组合,没有什么我做不了的了。

  原文链接: dzone 翻译: ImportNew.com - mingyuan

  译文链接: http://www.importnew.com/15958.html