mongodb 映射实体
当今的NoSQL格局包括许多非常有能力的竞争者,它们以多种不同方式解决大数据问题。 这些竞争者之一就是功能强大的MongoDB 。 MongoDB是一种面向文档的无模式存储解决方案,使用JSON样式的文档来表示,查询和修改数据。
MongoDB有据可查,易于安装和设置,并且易于扩展。 它支持复制,分片,索引和映射/归约等熟悉的概念。 MongoDB开源社区非常庞大且活跃。 MongoDB拥有许多大型和高流量的生产部署,包括迪士尼,Craigslist,Foursquare,Github和SourceForge。 MongoDB是一个10gen.com创建和维护的开源项目,该公司是由DoubleClick的前高管创建的。 除了出色的社区支持(10gen参与其中)之外,10gen还提供商业支持。
MongoDB的优势在于它是一个非常易于接近的NoSQL解决方案。 当我第一次进入NoSQL数据库世界时,我抽样了许多基于Java的解决方案,发现自己花了很多时间弄清楚什么是列族,Hadoop与HBase的关系以及ZooKeeper到底是什么? 当我最终弄清楚了所有内容后,还发现诸如Cassandra和HBase之类的产品显然是对NoSQL难题非常可靠且令人鼓舞的解决方案。 与其他解决方案相比,在开始编写代码之前,MongoDB易于掌握,需要克服的概念较少。
像任何软件一样,MongoDB显然并非没有缺陷。 在MongoDB期间,我遇到了一些我认为是“ Gotchas”的事情:
MongoDB的管理通常是使用Javascript客户端控制台应用程序完成的,该应用程序使诸如数据迁移和操作之类的复杂任务变得轻而易举,并使用Javascript编程语言进行了完全编程。 在本文中,我们将显示使用此控制台的示例。 如今,MongoDB社区将其称为驱动程序,提供了无数的生产质量的MongoDB客户。 通常,每种编程语言都有一个驱动程序,并且涵盖了所有流行的编程语言以及一些不太流行的语言。 本文介绍了如何将Java驱动程序用于MongoDB,并将其与使用ORM库(MJORM)进行比较。
对象关系映射是解决NoSQL数据存储的最新趋势已带给应用程序程序员生命的众多有趣问题之一。 对象关系映射(ORM)是指将传统上存储在RDBMS中的持久数据映射到应用程序使用的对象。 这使得处理数据对于应用程序所使用的语言更加流畅和自然。
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许可的谷歌代码项目 。 该项目使用maven构建,并且maven工件存储库当前由google code subversion服务器托管。 在撰写本文时,MJORM的最新稳定发行版是0.15,并且在生产环境中有几个项目正在使用。
Maven用户首先将MJORM maven存储库添加到其pom.xml文件中,以使MJORM工件可用于其项目:
然后依赖项本身:
这将使您能够在应用程序中导入和使用MJORM类。 如果您不使用maven,则需要手动下载MJORM库以及MJORM pom.xml中列出的依赖项。
现在已经有了相关性,是时候开始编写代码了。 我们将从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类型,该类型是一个12字节的二进制值,表示为十六进制字符串。 尽管MongoDB要求集合中的每个文档都具有唯一的ID,但并不要求ID的类型为ObjectId
。 当前,MJORM仅支持ObjectId
类型的ID,并将其表示为String
。
您可能还已经注意到Author
对象没有ID。 这是因为它将是Book
文档的子文档,因此不需要ID。 请记住,MongoDB仅在集合中的根级别文档上需要ID。
下一步是创建XML映射文件,MJORM将使用该映射文件将MongoDB文档映射到这些对象。 为了进行演示,我们将为每个对象创建一个文档,但是将所有映射放入单个XML文件或根据需要将它们分开是完全合理的。
这是Author.mjorm.xml
:
并且: Book.mjorm.xml
:
映射文件很容易解释。 descriptors
元素是根元素,并且必须存在于每个映射文件中。 在其下是object
元素,这些object
元素定义了要映射到MongoDB文档的每个类。 然后, object
包含一些property
元素,这些元素描述POJO上的所有属性以及它们如何映射到MongoDB文档上的属性。 property
必须至少包含一个name
元素,这是POJO上的属性名称和MongoDB文档上的属性名称。 可以选择添加column
属性,以在MongoDB文档上指定备用属性名称。
具有id
属性的property
属性被视为对象的唯一标识符。 一个object
只能包含一个具有id
属性的property
元素。 auto
属性告诉MJORM持久化该属性时,它应该自动为该属性生成一个值。
转到Google代码上的MJORM项目网站,以获取有关XML映射文件的更详细描述。
现在,我们已经创建了数据模型并创建了映射文件,以告诉MJORM如何将POJO进出MongoDB进行编组和取消编组,我们可以从有趣的东西开始。 首先,我们必须打开与MongoDB的连接:
Mongo mongo = new Mongo(
new MongoURI("mongodb://localhost/mjormIsFun")); // 10gen driver
Mongo
对象来自于10gen的家伙编写的Java驱动程序。 本示例打开与本地MongoDB实例的连接,并使用mjormIsFun
数据库。 接下来,我们创建MJORM ObjectMapper
。 当前,MJORM中可用的ObjectMapper
接口的唯一实现是使用上述XML架构的XmlDescriptorObjectMapper
,尽管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 driver
MongoDao dao = new MongoDaoImpl(db, objectMapper);
我们首先要做的是获取10gen驱动程序的DB
对象的实例。 之后,我们创建我们的MongoDao
为其提供DB
对象和我们之前创建的ObjectMapper
。 我们准备开始持久存储数据,让我们创建一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
方法,并向MongoDao
传递集合名称“ books
”和我们的Book
对象。 然后, DBObject
使用我们之前创建的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();
// 'db' is our DB object from earlier
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
,但它仍然存在。 这是由于MongoDB的无模式性质。 我们不能要求集合中的文档包含任何属性(_id属性除外),因此MongoDB完全可以创建没有Author
的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项目提供的文档或它提供的MongoDao
界面。
希望本文引起了MongoDB和MJORM的兴趣。 MongoDB是一个出色的NoSQL数据存储,具有许多很棒的功能,并且肯定会存在很长时间。 如果最终在Java项目中使用它,那么您可能还会考虑使用MJORM库来满足您的ORM需求,如果是这样,则对任何功能请求,错误报告,文档或源代码补丁都将不胜感激!
是一位经验丰富的高级工程师和团队负责人,拥有超过十三年的经验,专门研究Java / Java EE / Spring Framework / Linux内部和管理。 Brian在底层(0名以上员工)互联网创业公司,将他们推向市场以及构建/维护产品方面具有丰富的经验。 他是IaaS,云,PHP和Linux管理方面的专家,从采购,安装和配置产品以及企业硬件和软件基础结构(包括负载平衡,数据库,Web等)的采购,安装和配置。您可以在Twitter的Twitter上关注Brian。
翻译自: https://www.infoq.com/articles/mongodb-java-orm-bcd/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1
mongodb 映射实体