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

MongoDB、Java与对象关系映射

MongoDB介绍当今NoSQL领域中有很多有力的竞争者通过多种方式来处理海量数据问题。其中重要的解决方案之一就是MongoDB。MongoDB是面向文档的弱结构化存储方案,使用JSON格式来展现、查询和修改数据。MongoDB文档相当完备,扩展规模与安装一样简单。它提供冗

MongoDB介绍

当今NoSQL领域中有很多有力的竞争者通过多种方式来处理海量数据问题。其中重要的解决方案之一就是MongoDB。MongoDB是面向文档的弱结构化存储方案,使用JSON格式来展现、查询和修改数据。

MongoDB文档相当完备,扩展规模与安装一样简单。它提供冗余、切片、索引以及map/reduce等概念支持。MongoDB的开源社区非常大且非常活跃。MongoDB在很多大型产品中被实际运用,如:Disney, Craigslist, Foursquare, Github 和SourceForge。MongoDB是一个开源项目,由10gen.com建立并维护,该公司由DoubleClick的前任执行人员创立。同时,10gen也提供了极好的商业支持与参与建设。

MongoDB 与 NoSQL: 缺陷与优势

MongoDB作为一个可用NoSQL方案具有很多优势。我刚开始接触nosql数据库了解了一系列基于Java的方案,并且花了大量的时间来弄懂什么是列家族,Hadoop与HBase的关系,ZooKeeper到底是什么。当我终于全部清楚之后,发现Cassandra与HBase确实是对于NoSQL领域非常可靠、可信赖的解决方案。但与其他的解决方案相比,MongoDB让我在能够开始写代码之前,不用理解那么多的概念。

与其他软件相似,MongoDB也存在缺陷。经过一段时间使用MongoDB,我列举经历过并需要注意的一些事情,我成为“Gotchas”:

● 不要按照关系型数据库来思考。这很明显,MongoDB使得构建和执行复杂查询变得非常容易。当实际使用的时候,你会主要关注于效率问题(像我一样)。

● MongoDB的索引是二进制的树。如果你不是很熟悉B-tree,可能需要了解一下。这些都涉及到构建符合提供查询条件需求的建立索引的方式。

● 小心的设计索引结构。这涉及到上面提到的B-tree。刚开始我的索引包含文档中的很多字段,以防我会使用到他们。不要犯同样的错误。我有一个很小集合的索引(大约1千万记录)增长到超过17GB的空间,比集合本身还大。你应该不会想要索引一个包含成百上千个实体的列表字段。

● MongoDB采用了非常有意思的方式来实现NoSQL:采用BSON作为存储,JSON作为展示,Javascript用于管理和Map/Reduce。因此也引起了一些小问题比如这个 (破坏了Number和Long的相等操作),在MongoDB逐渐流行之后,可能会不断的展示出来。

MongoDB, 命令行与驱动

MongoDB基本是使用Javascript客户端命令行程序来进行复杂任务管理的,如数据整合和简单信息处理,编程都是完全使用Javascript语言来的。本文中,我们会展示命令行的使用示例。现在有大量的MongoDB客户端产品提供,并且由MongoDB社区来支持驱动。通常每种编程语言都有驱动,并且所有流行的语言都有包括,一些不那么流行的也包含在内。这篇文章展示了使用MongoDB的Java驱动,并使用一个ORM库(MJORM)与之进行比较。

介绍 MJORM: MongoDB的ORM方案

在解决的众多有意思的问题中,最近NoSQL数据存储在开发者中主要的问题趋势就是对象关系映射。对象关系映射就是将传统中保存在关系型数据库中的持久化数据映射为在应用程序中使用的对象。这使得编程语言使用起来更加流畅和自然。

MongoDB面向文档的架构使得它非常适合对象关系映射,因为文档本身就是以对象形式存储的。可惜没有太多的MongoDB的Java对象关系映射库,但是还是有一些,如morphia-(A type-safe Java library for MongoDB), spring-data(SpringData项目的MongoDB实现)

这些ORM库大量使用了注解,因为一些原因对我不适合,其中最重要的就是这些被注解的对象在多个项目中的兼容性问题。这让我开始了mongo-Java-orm 或者 “MJORM” (发音 me-yorm)项目,一个MongoDB的Java对象关系映射项目。MJORM是在MIT许可之下,并且在发布在了google code project。项目采用maven构建,并且maven构件仓库托管于google code版本控制服务器。MJORM的最新可用发布版本为0.15,已经由一些项目使用与生产环境中。

开始使用ORM

加入MJORM 库

Maven的使用者首先应当在pom.xml中加入MJORM的maven仓库,使得MJORM构件可用。

 

    mjorm-webdav-maven-repo  

    mjorm maven repository  

    http: 

    default  

 

然后加入依赖:

 

    com.googlecode  

    mongo-Java-orm  

    0.15  

 

这样就可以在应用中引入MJORM代码。假如没有使用maven,则你需要手动下载MJORM的pom.xml中列举的所有依赖。 建立 POJOs依赖已经导入,可以开始编码了。我们从POJO开始:

class Author {  

    private String firstName;  

    private String lastName;  

}  

class Book {  

    private String id;  

    private String isbn;  

    private String title;  

    private String description;  

    private Author author;  

我们在这个对象模型中的描述是,作者有ID、姓和名,书有ID、ISNB、标题、描述和作者。 你可能注意到书的id属性是一个字符串,这是为了适应MongoDB的对象ID类型。MongoDB的ID是一个12字节的二进制值显示为一个十六进制的字符串。MongoDB要求集合中的每个文档都必须有一个唯一id,但不要求一定要是ObjectId。目前MJORM只支持ObjectId,并且显示为字符串。 你也可能注意到了Author没有id字段。这是因为Book是它的父文档,因此不需要有id。记住,MongoDB只要求集合中的文档在根级别的id。 创建XML映射文件 下一个步骤就是建立XML映射文件,MJORM能够将MongoDB文档转换为对象。我们为每个文档创建一个对象作为示范,无论将所有的映射放在一个XML文件中还是分开都是可以的。

Author.mjorm.xml:

 

 

          

 

Book.mjorm.xml:

 

 

          

 

这些映射文件能够很好的自解释。descriptors 元素是根元素,必须包含在每个映射文件中。在它下面是object元素定义了文档与之对应的类。Object包含的property 元素主要用于描述POJO中的属性以及这些属性如何与MongoDB中的文档想对应。property 元素至少必须包含一个name 属性,这个元素就是POJO和MongoDB的文档中的属性名称。column 属性则是可选的,用于特定一个在MongoDB文档中的可选属性名称。 property 元素当中的id属性应该是对象的唯一识别。一个对象只能有一个property 元素包含id属性。auto 的设置会使得MJORM在持久化时为该属性自动生成一个值。 可以在google code的MJORM项目主页中查看XML映射文件的更多细节描述。 整合POJO与XML我们创建了数据模型以及映射文件,使得MJORM可以从MongoDB序列号以及反序列号POJO。我们可以进行一些有意思的事情了,首先打开MongoDB的链接:

Mongo mongo = new Mongo(  

         new MongoURI("mongodb://localhost/mjormIsFun")); // 10gen driver 

Mongo 对象是由10gen编写的Java驱动提供的。示例中连接了一个本地的MongoDB实例中的mjormIsFun数据库。接下来我们创建MJORM ObjectMapper 。目前ObjectMapper 在MJORM中的唯一实现就是XmlDescriptorObjectMapper,使用XML结构描述信息。可能之后会增加对注解或其他结构定义的支持。

XmlDescriptorObjectMapper objectMapper = new XmlDescriptorObjectMapper();  

mapper.addXmlObjectDescriptor(new File("Book.mjorm.xml"));  

mapper.addXmlObjectDescriptor(new File("Author.mjorm.xml")); 

建立好了XmlDescriptorObjectMapper 并且加入了映射文件。接下来建立由MJORM提供的MongoDao 对象的实例。

DB db = mongo.getDB("mjormIsFun");  

MongoDao dao = new MongoDaoImpl(db, objectMapper); 

首先我们要获得10gen驱动提供的DB对象实例。然后使用DB和ObjectMapper 建立MongoDao 。我们准备开始持久化数据,建立一个Book 然后保存到MongoDB中。

Book book = new Book();  

book.setIsbn("1594743061");  

book.setTitle("MongoDB is fun");  

book.setDescription("...");  

book = dao.createObject("books", book);  

System.out.println(book.getId());  

首先建立Book 对象并且填值,然后调用MongoDao 的 createObject 方法,将Book 对象传入”books” 的集合中。MJORM会按照之前的xml映射文件将Book 转换为DBObject (这是10gen的Java驱动使用的基本类型),并保存一个新的文档进”books” 集合。MJORM返回Book对象时,id属性会被填充。请注意,MongoDB默认是不需要在使用前建立数据库或集合的,系统会在需要时自动创建,这可能会造成某些困扰。在MongoDB的命令行中查看Book对象大概如下:

> db.books.find({_id:ObjectId("4f96309f762dd76ece5a9595")}).pretty()  

{  

         "_id":          ObjectId("4f96309f762dd76ece5a9595"),  

         "isbn":         "1594743061",  

         "title":        "MongoDB is fun",  

         "description":  "..." 

我们来看看假如不用MJORM而直接使用10gen的Java驱动,如何使用createObject 方法:

Book book = new Book();  

book.setIsbn("1594743061");  

book.setTitle("MongoDB is fun");  

book.setDescription("...");  

DBObject bookObj = BasicDBObjectBuilder.start()  

         .add("isbn",              book.getIsbn())  

         .add("title",             book.getTitle())  

         .add("description",       book.getDescription())  

         .get();  

DBCollection col = db.getCollection("books");  

col.insert(bookObj);  

ObjectId id = ObjectId.class.cast(bookObj.get("_id"));  

System.out.println(id.toStringMongod());  

下面进行对象的查询:

Book book = dao.readObject("books", "4f96309f762dd76ece5a9595", Book.class);  

System.out.println(book.getTitle());  

readObject 方法根据给定文档的id从指定的集合中读取文档,转换为对象(再次使用映射文件)并返回。 敏锐的读者会注意到Book还没有指定Author,仍然保存了。这归咎于MongoDB的结构不敏感的特性。我们不能要求集合中的文档包含所有属性(id属性是必须的),所有在MongoDB中没有Author的Book是可以的。我们现在为Book添加一个Author并且更新一下:

Author author = new Author();  

author.setFirstName("Brian");  

author.setLastName("Dilley");  

book.setAuthor(author);  

dao.updateObject("books", "4f96309f762dd76ece5a9595", book); 

现在Book就包含了Author,并且在MongoDB中持久化了。现在在命令行查看了Book:

> db.books.find({_id:ObjectId("4f96309f762dd76ece5a9595")}).pretty()  

{  

         "_id":          ObjectId("4f96309f762dd76ece5a9595"),  

         "isbn":         "1594743061",  

         "title":        "MongoDB is fun",  

         "description":  "..." 

         "author": {  

             "firstName": "Brian",  

             "lastName": "Dilley" 

         }  

可以看到持久化的Book中已经包含了author。不使用MJORM来操作一遍:

Author author = new Author();  

author.setFirstName("Brian");  

author.setLastName("Dilley");  

book.setAuthor(author);  

DBObject bookObj = BasicDBObjectBuilder.start()  

         .add("isbn",              book.getIsbn())  

         .add("title",             book.getTitle())  

         .add("description",       book.getDescription())  

         .push("author")  

                 .add("firstName",         author.getFirstName())  

                 .add("lastName",  author.getLastName())  

                 .pop()  

         .get();  

DBCollection col = db.getCollection("books");  

col.update(new BasicDBObject("_id", bookObj.get("_id")), bookObj); 

对于MongoDao 方法的深入讨论已经超出了本文的范围。对于将MJORM有兴趣用于实际项目中的用户强烈建议了解一下MJORM项目提供的相关文档,或者MongoDao 接口提供的相关用法。

总结

希望这篇文章对MongoDB和MJORM的亮点有所展示。MongDB是一个优秀的呃NoSQL数据存储,有着大量优秀的特性,会是NoSQL市场中长期竞争者。若你会在一个Java项目中使用MongoDB,希望你也能够考虑使用MJORM作为你的ORM框架。十分欢迎大家提交特性需求、错误异常报告、文档和源码修正。

作者 Bio

Brian Dilley 是一个经验丰富的高级工程师以及项目领导,在Java/Java EE /Spring Framework/Linux内部结构理解和管理有着超过13年的经验。Brian对于创业公司有很多经验,推向市场,构建/维护产品等。他是Iaas、cloud、PHP和Linux的专家,熟悉产品的采购、安装及配置定义,以及公司的软硬件架构包括负载均衡、数据库、微博等。可以follow Brian的 Twitter 。


推荐阅读
  • 本文详细介绍了如何搭建一个高可用的MongoDB集群,包括环境准备、用户配置、目录创建、MongoDB安装、配置文件设置、集群组件部署等步骤。特别关注分片、读写分离及负载均衡的实现。 ... [详细]
  • 深入解析:存储技术的演变与发展
    本文探讨了从单机文件系统到分布式文件系统的存储技术发展过程,详细解释了各种存储模型及其特点。 ... [详细]
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • 本文详细介绍了如何在 Ubuntu 14.04 系统上搭建仅使用 CPU 的 Caffe 深度学习框架,包括环境准备、依赖安装及编译过程。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • 调试利器SSH隧道
    在开发微信公众号或小程序的时候,由于微信平台规则的限制,部分接口需要通过线上域名才能正常访问。但我们一般都会在本地开发,因为这能快速的看到 ... [详细]
  • 精选10款Python框架助力并行与分布式机器学习
    随着神经网络模型的不断深化和复杂化,训练这些模型变得愈发具有挑战性,不仅需要处理大量的权重,还必须克服内存限制等问题。本文将介绍10款优秀的Python框架,帮助开发者高效地实现分布式和并行化的深度学习模型训练。 ... [详细]
  • 如何在U8系统中连接服务器并获取数据
    本文介绍了如何在U8系统中通过不同的方法连接服务器并获取数据,包括使用MySQL客户端连接实例的方法,如非SSL连接和SSL连接,并提供了详细的步骤和注意事项。 ... [详细]
  • 大数据领域的职业路径与角色解析
    本文将深入探讨大数据领域的各种职业和工作角色,帮助读者全面了解大数据行业的需求、市场趋势,以及从入门到高级专业人士的职业发展路径。文章还将详细介绍不同公司对大数据人才的需求,并解析各岗位的具体职责、所需技能和经验。 ... [详细]
  • 本文详细介绍了在 Ubuntu 系统上搭建 Hadoop 集群时遇到的 SSH 密钥认证问题及其解决方案。通过本文,读者可以了解如何在多台虚拟机之间实现无密码 SSH 登录,从而顺利启动 Hadoop 集群。 ... [详细]
  • 在List和Set集合中存储Object类型的数据元素 ... [详细]
  • 本文探讨了 Kafka 集群的高效部署与优化策略。首先介绍了 Kafka 的下载与安装步骤,包括从官方网站获取最新版本的压缩包并进行解压。随后详细讨论了集群配置的最佳实践,涵盖节点选择、网络优化和性能调优等方面,旨在提升系统的稳定性和处理能力。此外,还提供了常见的故障排查方法和监控方案,帮助运维人员更好地管理和维护 Kafka 集群。 ... [详细]
  • Hadoop 2.6 主要由 HDFS 和 YARN 两大部分组成,其中 YARN 包含了运行在 ResourceManager 的 JVM 中的组件以及在 NodeManager 中运行的部分。本文深入探讨了 Hadoop 2.6 日志文件的解析方法,并详细介绍了 MapReduce 日志管理的最佳实践,旨在帮助用户更好地理解和优化日志处理流程,提高系统运维效率。 ... [详细]
author-avatar
Json
技术QQ交流群:294088839.
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有