MongoDB、Java與物件關係對映

陳晨發表於2012-05-10

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程式碼。假如沒有使用maven,則你需要手動下載MJORM的pom.xml中列舉的所有依賴。 建立 POJOs依賴已經匯入,可以開始編碼了。我們從POJO開始:

 

我們在這個物件模型中的描述是,作者有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 物件是由10gen編寫的Java驅動提供的。示例中連線了一個本地的MongoDB例項中的mjormIsFun資料庫。接下來我們建立MJORM ObjectMapper 。目前ObjectMapper 在MJORM中的唯一實現就是XmlDescriptorObjectMapper,使用XML結構描述資訊。可能之後會增加對註解或其他結構定義的支援。

 

 

建立好了XmlDescriptorObjectMapper 並且加入了對映檔案。接下來建立由MJORM提供的MongoDao 物件的例項。

 

 

首先我們要獲得10gen驅動提供的DB物件例項。然後使用DB和ObjectMapper 建立MongoDao 。我們準備開始持久化資料,建立一個Book 然後儲存到MongoDB中。

 

 

首先建立Book 物件並且填值,然後呼叫MongoDao 的 createObject 方法,將Book 物件傳入”books” 的集合中。MJORM會按照之前的xml對映檔案將Book 轉換為DBObject (這是10gen的Java驅動使用的基本型別),並儲存一個新的文件進”books” 集合。MJORM返回Book物件時,id屬性會被填充。請注意,MongoDB預設是不需要在使用前建立資料庫或集合的,系統會在需要時自動建立,這可能會造成某些困擾。在MongoDB的命令列中檢視Book物件大概如下:

 

 

我們來看看假如不用MJORM而直接使用10gen的Java驅動,如何使用createObject 方法:

 

 

下面進行物件的查詢:

 


 

readObject 方法根據給定文件的id從指定的集合中讀取文件,轉換為物件(再次使用對映檔案)並返回。 敏銳的讀者會注意到Book還沒有指定Author,仍然儲存了。這歸咎於MongoDB的結構不敏感的特性。我們不能要求集合中的文件包含所有屬性(id屬性是必須的),所有在MongoDB中沒有Author的Book是可以的。我們現在為Book新增一個Author並且更新一下:

 


 

現在Book就包含了Author,並且在MongoDB中持久化了。現在在命令列檢視了Book:

 


 

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

 



 

對於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     本文由陳晨(@一酌散千憂)編譯並投稿於伯樂線上。如果您也願意 分享一份自己的原創/譯文,可以 從這裡開始

 【如需轉載,請標註並保留原文連結、譯文連結和譯者等資訊,謝謝合作!】

 

相關文章