`

MongoDB、Java及ORM

 
阅读更多

MongoDB简介

目前有很多互相竞争的NoSQL产品,它们使用的方式不尽相同,但都能很好地解决大数据问题。MongoDB就是其中一款非常不错的产品。MongoDB是面向文档、无Schema的存储解决方案,它用JSON风格的文档展现、查询、修改数据。

MongoDB有很丰富的文档,安装和设置都很简单,而且易于扩展。它支持大家熟知的复制、分片、索引和Map/Reduce等概念。MongoDB开源社区的规模很大,也很活跃。让MongoDB引以为豪的是,包括Disney、Craigslist、Foursquare、Github和SourceForge在内的大型、高流量生产环境都已经部署了MongoDB。MongoDB是个开源项目,由DoubleClick前高管们创办的10gen.com公司创建和维护。除了很积极地参与社区支持外,10gen也提供商业支持。

MongoDB和NoSQL的优劣势

作为NoSQL解决方案,MongoDB的优势是很容易上手。在我第一次深入研究NoSQL数据库的时候,尝试了很多基于Java的解决方案,我发现要搞清楚什么是列族(column family)、Hadoop和HBase之间是什么关系、ZooKeeper到底是什么非常费时间。我最终想明白这些问题的时候,才明白Cassandra、HBase等产品都是非常完善的NoSQL解决方案。和其他解决方案相比,MongoDB则更容易掌握一些,开始写代码之前不需要理解太多的概念。

很显然,MongoDB和任何软件一样都存在缺陷。在学习、使用MongoDB的过程中,我遇到过几件可算是“陷阱”的事情:

  • 不要把它用成RDBMS。这一点看起来显而易见,但在MongoDB里创建、执行复杂查询都很容易,以至于到了想用它做实时查询的时候,你可能才会发现自己已经做过头了,而且可能会碰到性能问题。(我以前就犯过这样的错)
  • MongoDB的索引是Binary Tree。如果你不太熟悉B-Tree,应该研究一下。查询条件的顺序要和创建索引的顺序相匹配。
  • 精心设计索引。这和前面提到的B-Tree有关系。我刚开始创建的几个索引都包含文档里的很多字段,因为总是想着以后可能会查询它们,这种想法你应该能够理解。不要犯这样的错误。我曾给一个很小的集合(大约一千万条记录)创建了一个索引,这个索引后来增长到17GB,比集合本身还要大。如果某个数组字段可能会包含成百上千的条目,你可能不会给它创建索引。
  • MongoDB支持NoSQL的方法非常有趣,它用BSON存储、用JSON表示,管理和Map/Reduce则用了JavaScript。这样一来,等MongoDB发展的时间足够久、和更流行的大数据解决方案一样长的时候,MongoDB必然会出现一些奇怪的小问题,比如在NumberLong上使用等于运算符会判断失败

MongoDB、控制台、驱动程序

MongoDB的管理通常可以在一个JavaScript客户端控制台应用上进行,控制台应用能简化数据迁移和操作等复杂任务;你也完全可以用JavaScript语言编程实现MongoDB的管理。在这篇文章里,我们会示范控制台的使用。现在的MongoDB客户端产品非常多,它们都具备能投入生产环境的品质,MongoDB社区也称它们为驱动程序。一般来说,每种编程语言都有各自的驱动程序,这些驱动程序能覆盖所有流行的编程语言,还有一些并不是很流行的编程语言。本文将展示MongoDB的Java驱动程序该如何使用,也会和使用ORM库(MJORM)的方式进行比较。

MJORM简介:MongoDB的ORM解决方案

NoSQL数据存储还有很多有趣的问题需要解决,最近让应用程序员比较关心的是对象关系映射(ORM)。ORM是指持久化数据和应用所用对象之间的映射,持久化数据过去都存储在关系型数据库里。ORM能让处理数据的过程更加流畅、更加贴近编写应用的语言。

MongoDB面向文档的架构让它很容易进行ORM,因为它存储的文档本身就是对象。不过可惜的是,可用于MongoDB的Java ORM库还不是很多,目前只有morphia(针对MongoDB的Java库,是类型安全的)和spring-data(Spring Data综合项目的MongoDB实现)。

这些ORM库使用了大量注解,出于很多原因,我并不倾向于使用注解,其中最重要的是被注解的对象在多个项目之间的可移植性问题。所以我创建了mongo-Java-orm项目(MJORM,发音为me-yorm),它是针对MongoDB的Java ORM。MJORM使用MIT许可,放在了Google Code上。项目用Maven构建,Maven的工件库目前托管在Google Code的Subversion服务器上。写这篇文章的时候,MJORM最新的稳定发布版本是0.15,个别项目已经在生产环境里使用了。

MJORM入门

将MJORM库添加到项目里

Maven用户首先要将MJORM的Maven仓库添加到pom.xml文件里,以便自己的项目能使用MJORM工件:

<repository> 	
    <id>mjorm-webdav-maven-repo</id>
    <name>mjorm maven repository</name>
    <url>http://mongo-Java-orm.googlecode.com/svn/maven/repo/</url>
    <layout>default</layout> 
</repository> 

然后添加依赖本身:

<dependency>
    <groupid>com.googlecode</groupid>
    <artifactid>mongo-Java-orm</artifactid>
    <version>0.15</version>
</dependency>

这样你就能把MJORM类导入到自己的应用里并使用它们。如果你没用Maven,那你需要手动下载MJORM库,还有MJORM pom.xml里列出的所有依赖。

创建POJO

依赖关系处理好之后,就开始编写代码吧。我们先编写Java POJO:

class Author {
    private String firstName;
    private String lastName;
    // ... setters and getters ...
}

class Book {
    private String id;
    private String isbn;
    private String title;
    private String description;
    private Author author;
    // ... setters and getters ...
}

上面的对象模型描述了作者和书,作者有一个ID、还有姓氏和名字,书的描述信息则包含ID、ISBN号、标题、描述信息和作者。

可以看到书的ID属性是一个String,它会适应成MongoDB的ObjectId类型,ObjectId类型是个十二字节的二进制值,用十六进制的字符串来表示。虽然MongoDB要求所有集合里的每个文档都要有一个唯一的ID,但并没有要求ID必须是ObjectId类型。目前MJORM支持的ID类型只有ObjectId,而且会把它们表示成String。

你可能已经注意到,Author对象没有ID。这是因为Author是Book文档的子文档,所以就没必要非得有一个ID了。请记住,MongoDB的ID只需要放在一个集合的根级别文档中。

创建XML映射文件

下一步是创建XML映射文件,MJORM会用这些映射文件把MongoDB文档映射成对象。在本文的演示里,我们会给两个对象各创建一个文档,但真正合理的做法是把所有的映射都放在一个XML文件里,或者根据实际需要进行分割。

下面是Author.mjorm.xml:

<?xml version="1.0"?>
<descriptors>
    <object class="Author">
        <property name="firstName" />
        <property name="lastName" />
    </object>
</descriptors>

Book.mjorm.xml是:

<?xml version="1.0"?>
<descriptors>
    <object class="Book">
        <property name="id" id="true" auto="true" />
        <property name="isbn" />
        <property name="title" />
        <property name="description" />
        <property name="author" />
    </object>
</descriptors>

映射文件完全能自解释。descriptors元素是根元素,所有的映射文件都要有。根元素下面是object元素,用来定义要被映射到MongoDB文档的类。object会包含property元素,用来描述POJO的所有属性,以及它们怎样映射到MongoDB文档的属性。property元素至少要有一个name属性,这是POJO属性的名称,也是MongoDB文档属性的名称。property元素还可以添加一个column属性,指定MongoDB文档里备用的属性名称。

包含id属性的property元素会被看作是对象的唯一标识符。一个object元素可以只包含一个带有id属性的property元素。auto属性是让MJORM在持久化这个属性时给它自动生成一个值。

要想了解有关XML映射文件更详细的说明,请移步至Google Code上的MJORM项目。

整合

我们现在已经创建好了数据模型,还有告诉MJORM在数据写入MongoDB时如何解析POJO、从MongoDB读取数据时如何封装POJO的映射文件,那我们就可以开始一段有趣的学习之旅了。首先我们必须打开到MongoDB的连接:

Mongo mongo = new Mongo(
    new MongoURI("mongodb://localhost/mjormIsFun")); // 10gen驱动程序

Mongo对象来自10gen员工编写的Java驱动程序。这个例子打开了一个到本地MongoDB实例的连接,使用mjormIsFun数据库。接下来我们创建MJORM里的ObjectMapper。目前MJORM里可用的ObjectMapper接口实现只有XmlDescriptorObjectMapper,它使用前面的XML Schema,MJORM以后的实现可能会支持注解或其他配置机制。

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"); // 10gen驱动程序
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()); // 4f96309f762dd76ece5a9595

我们先创建了Book对象,赋值之后调用了MongoDao的createObject方法,两个参数分别是集合名称“books”和Book对象。MJORM接着会用先前创建的XML映射文件把Book转换成DBObject(10gen的Java驱动程序所使用的基本对象类型),并把新的文档持久化到“books”集合中。然后MJORM会返回Book对象的实例,返回的Book对象实例带有生成的id属性。重点要注意的是,MongoDB在默认情况下并不会要求创建好数据库或集合后才能使用;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();

// ‘db’是我们先前创建的DB对象
DBCollection col = db.getCollection("books");
col.insert(bookObj);

ObjectId id = ObjectId.class.cast(bookObj.get("_id"));
System.out.println(id.toStringMongod()); // 4f96309f762dd76ece5a9595

现在我们来查询一下对象:

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

readObject方法用指定的id从特定集合中读取文件,然后将文件转换成相应的类(会再次使用先前的映射文件)并返回。

敏锐的你可能已经察觉到我们的Book还没Author,但Book仍然被持久化了。这正是MongoDB的无Schema特性。除了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。让我们从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现在包含一个作者。接着再看看不使用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项目的文档,或者是MJORM项目提供的MongoDao接口。

结论

希望这篇文章能让大家对MongoDB和MJORM开始感兴趣。方兴未艾的MongoDB是个很优秀的NoSQL数据存储产品,有很多很不错的特性。如果你要在Java项目里使用MongoDB,那你可以考虑用MJORM库来满足ORM需求。要是能提出功能需求、Bug报告、文档,或给源码打补丁,我们将不胜感激!

分享到:
评论

相关推荐

    基于Java的ORM框架Mongodb-ORM.zip

    mongodb-orm简介Mongodb ORM是基于java的ORM框架,简化了SDK的使用,使代码变得更清晰、简单。 与Ibatis类似,将查询、执行语句封装在xml中,与代码隔离。简称MQL。 项目中使用加入mongodb orm的支持包1. 添加jar...

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

    MongoDB的ORM(Object-Relational Mapping)框架使得Java开发者能够更方便地将数据模型与数据库交互,而无需关注底层的MongoDB API细节。在本文中,我们将讨论如何基于`mongodb-driver`开发一个简单的ORM实现,以...

    MongoDB、Java与对象关系映射

    MJORM是一个专门为MongoDB设计的Java ORM库,旨在提供一种更高效、更简洁的方式来处理MongoDB中的数据。相比于其他使用注解的ORM库,MJORM采用了一种不同的方法来实现对象与MongoDB之间的映射,这使得它在某些场景下...

    基于mongodb官方Java驱动的orm框架,允许子类嵌套.zip

    这个压缩包“基于mongodb官方Java驱动的orm框架,允许子类嵌套.zip”显然是一个ORM(对象关系映射)框架,旨在简化Java应用与MongoDB之间的数据操作,特别是支持子类的嵌套结构。 ORM框架允许开发者用面向对象的...

    MongoDb ORM 框架(构建类似 sql 的体验,体验风格与 wood 类似)

    MongoDB ORM(对象关系映射)框架是一种工具,它允许开发者使用类似SQL的方式来操作MongoDB数据库,从而在非关系型数据库中实现更加直观和高效的数据管理。MongoDB因其灵活性、可扩展性和高性能,在现代Web应用中被...

    mongodb的java驱动jar包3.7.0

    MongoDB的Java驱动是连接Java应用程序与MongoDB数据库的关键组件,3.7.0版本是这一驱动的一个稳定发行版。...在实际项目中,开发者还需要结合Spring Data MongoDB或者其他的ORM框架,以简化代码并提高开发效率。

    java mongodb orm

    private orm framework for mongdb

    可能java上最好用而且实时跟进官方版本的ORM,让您更加舒适地使用MongoDMongoDBPlugin.zip

    MongoDB Plugin可能java上最好用而且实时跟进官方版本的ORM,让您更加舒适地使用MongoDB。 与MongoDB版本基本同步(基于最新3.4.0) 使用方式更像是自然语言,用起来更舒适 几乎没有任何学习成本 支持MongoDB...

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

    7. **MJORM**:Mongo-Java-ORM(MJORM)是一个专门为MongoDB设计的Java ORM解决方案,它避免了过度依赖注解,解决了多项目间的兼容性问题。MJORM提供了一种更灵活的方式来映射Java对象到MongoDB文档,使得Java开发者...

    springmvc+mybatis+mongoDB

    总的来说,"springmvc+mybatis+mongoDB"的组合为现代Web应用提供了全面的解决方案,涵盖了后端控制逻辑、ORM操作以及非关系型数据库的存储。这种技术栈既能够充分利用Spring的全面功能,又能够满足处理不同类型数据...

    基于Java的Bee ORM框架设计与实现源码

    Bee ORM框架,一款面向互联网新时代的Java ORM解决方案,支持数据库分片、多种数据库连接,包括JDBC、Android和HarmonyOS平台,并兼容Cassandra、MongoDB等NoSQL数据库。该框架以快速、简便、智能为核心,旨在提升...

    互联网新时代的Java ORM框架

    Bee,互联网新时代的Java ORM框架,支持Sharding;JDBC,Android,HarmonyOS;支持多种关系型数据库,还支持NoSQL的Cassandra,Mongodb等;更快、更简单、更自动,开发速度快,运行快,更智能。一个简单,易用,功能...

    java spring+mongodb

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

    spring mongodb用到的jar包spring-date-mongodb1.4.2.zip

    它实现了ORM(对象关系映射)的概念,尽管MongoDB是一个NoSQL文档数据库,而不是传统的关系型数据库。这个框架提供了注解驱动的编程模型,允许开发者通过简单的接口定义来实现对MongoDB的数据操作。 **2. Spring ...

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

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

    mongodb+spring+hibernate集成入门demo

    在"mongodbjava"这个压缩包中,可能包含以下关键组件: 1. `pom.xml`:Maven项目的配置文件,将包含对MongoDB Java驱动、Spring Data MongoDB、Spring Framework和Hibernate等相关依赖的声明。 2. `...

    Mongo的ORM框架的学习Morphia

    Morphia是专门为MongoDB设计的一个强大的Java ORM框架,它提供了方便的方式来处理MongoDB文档与Java对象之间的转换。 首先,我们看到SpringMongoConfig类,这是Spring Data MongoDB的配置文件。这个类继承自...

    springboot整合mongodb+redis+mybatis+mysql

    SpringBoot 整合 MySQL 通常使用 `spring-boot-starter-jdbc` 或 `spring-boot-starter-data-jpa` 依赖,其中 JPA(Java Persistence API)是 Java 提供的 ORM(对象关系映射)标准,可以方便地进行对象与数据库表...

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

    Mongernate是针对Java的MongoDB对象关系映射(ORM)框架,它提供了类似Hibernate的功能,使得开发者可以更方便地在Java应用中操作MongoDB。 Mongernate的核心功能包括: 1. 对象映射:Mongernate允许我们将Java...

    java jquery mongodb/mysql 分页

    标题 "Java jQuery MongoDB/MySQL 分页" 涉及到的是在Web开发中常见的数据处理技术,主要包括Java后端的数据处理、前端jQuery库的使用以及数据库分页的概念。在这个场景中,Java通常作为服务器端语言处理请求,而...

Global site tag (gtag.js) - Google Analytics