`

MongoDB、Java与对象关系映射(转)

 
阅读更多

转载:http://developer.51cto.com/art/201205/334984.htm

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构件可用。

  1. <repository>  
  2.     <id>mjorm-webdav-maven-repo</id>  
  3.     <name>mjorm maven repository</name>  
  4.     <url>http://mongo-Java-orm.googlecode.com/svn/maven/repo/</url>  
  5.     <layout>default</layout>  
  6. </repository> 

然后加入依赖:

  1. <dependency>  
  2.     <groupId>com.googlecode</groupId>  
  3.     <artifactId>mongo-Java-orm</artifactId>  
  4.     <version>0.15</version>  
  5. </dependency> 

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

  1. class Author {  
  2.     private String firstName;  
  3.     private String lastName;  
  4.     // ... setters and getters ...  
  5. }  
  6.    
  7. class Book {  
  8.     private String id;  
  9.     private String isbn;  
  10.     private String title;  
  11.     private String description;  
  12.     private Author author;  
  13.     // ... setters and getters ...  

我们在这个对象模型中的描述是,作者有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:

  1. <?xml version="1.0"?> 
  2. <descriptors> 
  3.          <object> 
  4.                  <property name="firstName" /> 
  5.                  <property name="lastName" /> 
  6.          </object> 
  7. </descriptors> 

Book.mjorm.xml:

  1. <?xml version="1.0"?> 
  2. <descriptors> 
  3.          <object> 
  4.                  <property name="id" id="true" auto="true" /> 
  5.                  <property name="isbn" /> 
  6.                  <property name="title" /> 
  7.                  <property name="description" /> 
  8.                  <property name="author" /> 
  9.          </object> 
  10. </descriptors> 

这些映射文件能够很好的自解释。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的链接:

  1. Mongo mongo = new Mongo(  
  2.          new MongoURI("mongodb://localhost/mjormIsFun")); // 10gen driver 

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

  1. XmlDescriptorObjectMapper objectMapper = new XmlDescriptorObjectMapper();  
  2. mapper.addXmlObjectDescriptor(new File("Book.mjorm.xml"));  
  3. mapper.addXmlObjectDescriptor(new File("Author.mjorm.xml")); 

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

  1. DB db = mongo.getDB("mjormIsFun"); // 10gen driver  
  2. MongoDao dao = new MongoDaoImpl(db, objectMapper); 

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

  1. Book book = new Book();  
  2. book.setIsbn("1594743061");  
  3. book.setTitle("MongoDB is fun");  
  4. book.setDescription("...");  
  5. book = dao.createObject("books", book);  
  6. System.out.println(book.getId()); // 4f96309f762dd76ece5a9595 

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

  1. > db.books.find({_id:ObjectId("4f96309f762dd76ece5a9595")}).pretty()  
  2. {  
  3.          "_id":          ObjectId("4f96309f762dd76ece5a9595"),  
  4.          "isbn":         "1594743061",  
  5.          "title":        "MongoDB is fun",  
  6.          "description":  "..." 

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

  1. Book book = new Book();  
  2. book.setIsbn("1594743061");  
  3. book.setTitle("MongoDB is fun");  
  4. book.setDescription("...");  
  5. DBObject bookObj = BasicDBObjectBuilder.start()  
  6.          .add("isbn",              book.getIsbn())  
  7.          .add("title",             book.getTitle())  
  8.          .add("description",       book.getDescription())  
  9.          .get();  
  10. // 'db' is our DB object from earlier  
  11. DBCollection col = db.getCollection("books");  
  12. col.insert(bookObj);  
  13. ObjectId id = ObjectId.class.cast(bookObj.get("_id"));  
  14. System.out.println(id.toStringMongod()); // 4f96309f762dd76ece5a9595 

下面进行对象的查询:

  1. Book book = dao.readObject("books""4f96309f762dd76ece5a9595", Book.class);  
  2. System.out.println(book.getTitle()); // "MongoDB is fun" 

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

  1. Author author = new Author();  
  2. author.setFirstName("Brian");  
  3. author.setLastName("Dilley");  
  4. book.setAuthor(author);  
  5. dao.updateObject("books""4f96309f762dd76ece5a9595", book); 

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

  1. > db.books.find({_id:ObjectId("4f96309f762dd76ece5a9595")}).pretty()  
  2. {  
  3.          "_id":          ObjectId("4f96309f762dd76ece5a9595"),  
  4.          "isbn":         "1594743061",  
  5.          "title":        "MongoDB is fun",  
  6.          "description":  "..." 
  7.          "author": {  
  8.              "firstName""Brian",  
  9.              "lastName""Dilley" 
  10.          }  

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

  1. Author author = new Author();  
  2. author.setFirstName("Brian");  
  3. author.setLastName("Dilley");  
  4. book.setAuthor(author);  
  5. DBObject bookObj = BasicDBObjectBuilder.start()  
  6.          .add("isbn",              book.getIsbn())  
  7.          .add("title",             book.getTitle())  
  8.          .add("description",       book.getDescription())  
  9.          .push("author")  
  10.                  .add("firstName",         author.getFirstName())  
  11.                  .add("lastName",  author.getLastName())  
  12.                  .pop()  
  13.          .get();  
  14. DBCollection col = db.getCollection("books");  
  15. 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 。

 

英文原文:Brian Dilley 本文由陈晨(@一酌散千忧)编译并投稿于伯乐在线。如果您也愿意 分享一份自己的原创/译文,可以 从这里开始~

分享到:
评论

相关推荐

    MongoDB、Java与对象关系映射

    ### MongoDB、Java与对象关系映射 #### MongoDB简介与特性 MongoDB作为一种强大的NoSQL数据库,在处理非结构化数据方面有着显著的优势。它通过使用JSON(JavaScript Object Notation)格式来存储和检索数据,简化...

    MongoDB、Java与对象关系映射.pdf

    MJORM提供了一种更灵活的方式来映射Java对象到MongoDB文档,使得Java开发者能更自然地与MongoDB数据库进行交互。 8. **挑战与注意事项**:尽管MongoDB有诸多优点,但也有需要注意的地方。例如,不适合完全按关系型...

    mongodb java driver 2.11

    3. **文档模型**:Java驱动程序将MongoDB的BSON(Binary JSON)文档映射为Java对象,便于在Java代码中处理。`BasicDBObject`类用于构建和操作这些文档。 4. **异步编程支持**:除了同步API,2.11版本也提供异步API...

    mongodb 3.4.2 java包

    在MongoDB 3.4.2中,Java驱动程序支持将Java对象映射到MongoDB文档,反之亦然,这被称为“对象文档映射”(ODM)。这样,开发者可以轻松地在Java对象和数据库文档之间转换。 4. **查询和操作**:MongoDB的查询语言...

    java操作mongodb时,对象bean和DBObject相互转换的方法(推荐)

    在Java中操作MongoDB数据库时,常常需要将Java对象(对象Bean)与MongoDB的数据表示对象DBObject进行相互转换。这主要是因为MongoDB的驱动程序使用DBObject来存储和检索数据,而我们通常会用面向对象的方式来定义和...

    MongoDB Java Demo

    MongoDB使用`Document`对象来表示数据,它是一个键值对的映射,类似JSON对象。例如,创建一个简单的文档: ```java Document doc = new Document("name", "John").append("age", 30); ``` 插入文档到集合中: ```...

    Java与log4j2整合mongoDB需要的jar包

    Java是一种广泛使用的面向对象的编程语言,具有平台无关性,这使得它成为构建跨平台应用程序的理想选择。Log4j2是Apache的一个开源项目,它为Java应用程序提供了一种灵活的日志记录解决方案。相比早期的log4j,log4j...

    mongodb在java中小试牛刀

    3. **实体类(Mapping)**: 在使用Spring Data MongoDB时,通常需要创建Java对象(称为Document)来映射MongoDB的集合。这些类通常使用`@Document`注解来标识,并且可以通过`@Id`注解指定主键字段。 ```java @...

    mongoDB(含java版本和spring整合版+图形界面工具及说明文档)

    - Java驱动程序通过MongoClient对象与MongoDB服务器建立连接,然后通过Database和Collection对象来操作数据库和集合。 - Java驱动支持异步操作,提高并发性能,同时也支持MongoDB的高级特性,如聚合框架、地理空间...

    Java 解析xml 存入mongodb 返回org.json json包

    - 定义一个Java对象来映射XML数据的结构,比如`MyData`,包含字段以匹配XML元素。 - 在解析XML时,根据接收到的元素信息创建`MyData`对象实例。 - 使用MongoDB的`MongoDatabase`和`MongoCollection`接口,创建...

    Java将日期类型Date时间戳转换为MongoDB的时间类型数据

    将 Java 的日期类型 Date 转换为 MongoDB 的时间类型数据需要使用 SimpleDateFormat 类将 Date 对象转换为指定格式的字符串。这种方法可以将日期类型的数据转换为 MongoDB 可以识别的时间类型数据。 相关知识点: ...

    java mongodb orm 实现-基于mongodb-driver开发的ORM.pdf

    2. **内嵌文档映射**:支持内嵌文档的映射,即在Java对象中可以包含其他对象,对应MongoDB中的嵌入式文档。 3. **异步存储与批量存储**:提供异步存储方法,提高并发性能,并支持批量插入、更新和删除操作。 4. **...

    springmvc+mybatis+mongoDB

    通过XML或注解配置,MyBatis允许开发者编写SQL语句,将它们与Java对象映射起来,实现动态SQL和事务管理。在Spring MVC中,MyBatis可以通过Spring的SqlSessionFactoryBean和MapperScannerConfigurer进行整合,实现DAO...

    mongoDB DAO层封装

    在MongoDB与Java对象之间进行数据转换时,通常使用MongoDB的Java驱动程序中的Document类或Spring Data的MongoEntity或MongoDBObject。MongoDB的Document类可以直接映射到Java的Map对象,而Spring Data提供了...

    让Java EE再次变酷使用JPA和EJB构建基于MongoDB的网络服务

    2. **Hibernate JPA提供者**:负责对象关系映射,使Java EE应用程序能够操作MongoDB数据库。 3. **Hibernate OGM服务器**:作为接口层,将Java EE应用程序与MongoDB数据库连接起来。 4. **MongoDB数据库**:存储应用...

    relmongo:MongoDB的启用了Java关系的域模型持久性框架

    RelMongo Java框架提供了MongoDB域模型对象的关系映射。 该框架提供了OneToMany,OneToOne和ManyToOne之类的注释作为DBRef的替代,并允许级联操作和延迟加载。 RelMongo使用Spring数据mongodb和手动参考,这些参考...

    mongojack:Mongojack将Java对象映射到MongoDB文档。 基于Jackson JSON映射器,Mongojack允许您轻松将mongo对象作为POJO处理(插入,按ID或任何其他字段搜索,更新)

    由于MongoDB使用JSON的二进制形式BSON来存储其文档,因此JSON映射器是将Java对象映射到MongoDB文档的理想机制。 最好的Java JSON映射器是Jackson。 Jackson的解析/生成接口适合像手套一样序列化到MongoDB的文档。 ...

    java spring+mongodb

    Spring Data MongoDB项目使得与MongoDB数据库的交互变得简单,它提供了ORM(对象关系映射)功能,允许开发者使用Java对象直接操作MongoDB文档。 1. **Spring Data MongoDB入门** - **配置MongoDB**:首先,我们...

    mongodb连接jar包

    MongoDB Java驱动程序是Java开发者用来与MongoDB进行交互的主要工具,它提供了丰富的API来执行各种数据库操作。 在给定的压缩包文件中,我们有三个关键文件: 1. `mongo-java-driver-3.4.2-javadoc.jar`:这是...

    适用于java语言的MongoDB解决方案——Mongernate

    1. 对象映射:Mongernate允许我们将Java对象映射到MongoDB的文档。这样,开发者可以用面向对象的方式处理数据,而不需要直接编写SQL查询或使用低级MongoDB API。 2. 数据持久化:通过Mongernate,可以实现Java对象...

Global site tag (gtag.js) - Google Analytics