将MongoDB与Morphia结合使用
最近,我有機(jī)會(huì)使用MongoDB (與humongoous一樣),這是一個(gè)用C ++編寫的面向文檔的數(shù)據(jù)庫。 它是存儲(chǔ)結(jié)構(gòu)可能不同的文檔的理想選擇,它使用類似于JSON的格式,這意味著它支持與JSON類似的數(shù)據(jù)類型和結(jié)構(gòu)。 它提供了豐富而簡(jiǎn)單的查詢語言,仍然使我們能夠?yàn)榭焖贆z索的關(guān)鍵字段建立索引。 文檔存儲(chǔ)在集合中,這有效地限制了查詢的范圍,但是對(duì)于可以存儲(chǔ)在集合中的異構(gòu)數(shù)據(jù)的類型實(shí)際上沒有任何限制。 如果您需要學(xué)習(xí)MongoDB的基礎(chǔ)知識(shí),則MongoDB站點(diǎn)上的文檔不錯(cuò)。
Java中的MongoDB
Mongo Java驅(qū)動(dòng)程序基本上將所有文檔公開為鍵值對(duì)(顯示為map和值列表)。 這意味著,如果必須使用Java存儲(chǔ)或檢索文檔,則必須將POJO映射到該映射接口。 以下是通常需要編寫的代碼類型示例,以將文檔從Java保存到MongoDB:
BasicDBObject doc = new BasicDBObject();doc.put("user", "carfey");BasicDBObject post1 = new BasicDBObject(); post1.put("subject", "spam & eggs"); post1.put("message", "first!");BasicDBObject post2 = new BasicDBObject(); post2.put("subject", "sorry about the spam");doc.put("posts", Arrays.asList(post1, post2));coll.insert(doc);對(duì)于某些用例來說這很好,但是對(duì)于其他用例來說,最好有一個(gè)庫來為我們做繁瑣的工作。
輸入Morphia
Morphia是一個(gè)Java庫,其行為類似于MongoDB的ORM –它使我們能夠?qū)ava對(duì)象無縫映射到MongoDB數(shù)據(jù)存儲(chǔ)。 它使用注釋來指示類存儲(chǔ)在哪個(gè)集合中,甚至支持多態(tài)集合。 最好的功能之一是,它可以用于基于集合或?qū)傩约?jí)別的注釋自動(dòng)為集合建立索引。 這極大地簡(jiǎn)化了部署和推出變更。
我提到了同一集合中多種類型的多態(tài)存儲(chǔ)。 這可以幫助我們映射不同的文檔結(jié)構(gòu),并在某種程度上像Hibernate之類的鑒別器 。
這是一個(gè)示例,說明如何定義支持多態(tài)存儲(chǔ)和查詢的實(shí)體。 Return類是Order的子級(jí),并引用相同的collection-name。 查詢或存儲(chǔ)數(shù)據(jù)時(shí),Morphia將自動(dòng)處理多態(tài)性。 對(duì)于非多態(tài)的集合,您幾乎會(huì)做同樣的事情,但是不會(huì)有多個(gè)使用相同集合名稱的類。
注意:這實(shí)際上不是我建議存儲(chǔ)在MongoDB中的數(shù)據(jù)類型的示例,因?yàn)樗m合于傳統(tǒng)的RDBMS,但是很好地展示了原理。
@Entity("orders") // store in the orders collection @Indexes({ @Index("-createdDate, cancelled") }) // multi-column index public class Order {@Id private ObjectId id; // always required@Indexedprivate String orderId;@Embedded // let's us embed a complex objectprivate Person person;@Embeddedprivate List<Item> items;private Date createdDate;private boolean cancelled;// .. getters and setters aren't strictly required// for mapping, but they would be here }@Entity("orders") // note the same collection name public class Return extends Order {// maintain legacy name but name it nicely in mongodb@Indexed@Property("rmaNumber") private String rma;private Date approvedDate;private Date returnDate; }現(xiàn)在,在下面,我將演示如何查詢那些多態(tài)實(shí)例。 請(qǐng)注意,存儲(chǔ)數(shù)據(jù)時(shí)我們不必做任何特殊的事情。 MongoDB將className屬性與文檔一起存儲(chǔ),因此它可以支持多態(tài)獲取和查詢。 按照上面的示例,我可以通過執(zhí)行以下查詢所有訂單類型:
// ds is a Datastore instance Query<Order> q = ds.createQuery(Order.class).filter("createdDate >=", date); List<Order> ordersAndReturns = q.asList();// and returns only Query<Return> rq = ds.createQuery(Return.class).filter("createdDate >=", date); List<Return> returnsOnly = rq.asList();如果我只想查詢普通訂單,則必須使用className過濾器,如下所示。 這使我們能夠有效地禁用多態(tài)行為并將結(jié)果限制為單個(gè)目標(biāo)類型。
Query<Order> q = ds.createQuery(Order.class).filter("createdDate >=", cutOffDate).filter("className", Order.class.getName());List<Order> ordersOnly = q.asList();Morphia當(dāng)前使用className屬性來過濾結(jié)果,但是在將來的某個(gè)時(shí)候可能會(huì)使用一個(gè)鑒別符列,在這種情況下,您可能不得不過濾該值。
注意:在應(yīng)用程序啟動(dòng)期間的某個(gè)時(shí)刻,您需要注冊(cè)映射的類,以便Morphia可以使用它們。 詳細(xì)信息請(qǐng)參見此處。 下面是一個(gè)簡(jiǎn)單的示例。
Morphia m = ... Datastore ds = ...m.map(MyEntity.class); ds.ensureIndexes(); //creates all defined with @Indexed ds.ensureCaps(); //creates all collections for @Entity(cap=@CappedAt(...))文檔結(jié)構(gòu)變化問題
MongoDB中面向文檔的存儲(chǔ)的一個(gè)不錯(cuò)的功能之一是,它允許您將具有不同結(jié)構(gòu)的文檔存儲(chǔ)在同一集合中,但是仍然可以執(zhí)行結(jié)構(gòu)化查詢和索引值以獲得良好的性能。
不幸的是,Morphia并不真正喜歡這種方式,因?yàn)樗荚趯⑺写鎯?chǔ)的屬性映射到已知的POJO字段。 目前,我發(fā)現(xiàn)有兩種方法可以讓我們處理此問題。
第一個(gè)是禁用查詢驗(yàn)證。 這意味著將刪除數(shù)據(jù)存儲(chǔ)中存在但無法映射到我們的POJO的值,而不是將其炸掉:
// drop unmapped fields quietly Query<Order> q = ds.createQuery(Order.class).disableValidation();另一個(gè)選擇是使用地圖將所有非結(jié)構(gòu)化內(nèi)容存儲(chǔ)在單個(gè)存儲(chǔ)桶元素下。 它可以包含MongoDB驅(qū)動(dòng)程序支持的任何基本類型,包括列表和地圖,但不包含復(fù)雜對(duì)象,除非您已向Morphia注冊(cè)了轉(zhuǎn)換器(例如morphia.getMapper()。getConverters()。addConverter(new MyCustomTypeConverter()))。
@Entity("orders") public class Order {// .. our base attributes hereprivate Map<String, Object> attributes; // bucket for everything else ( }請(qǐng)注意,Morphia可能會(huì)在啟動(dòng)時(shí)抱怨它無法驗(yàn)證字段(因?yàn)榉盒吐暶鞑粐?yán)格),但是從當(dāng)前發(fā)行版(0.99)開始,它將正常工作并可以正常存儲(chǔ)任何屬性并檢索它們作為值的映射和列表。
注意:當(dāng)它從檢索到的文檔中填充一個(gè)松散類型的映射時(shí),它將使用基本的MongoDB Java驅(qū)動(dòng)程序類型BasicDBObject和BasicDBList。 它們分別實(shí)現(xiàn)Map和List,因此它們將與您期望的一樣工作,只是它們與您可能存儲(chǔ)的任何輸入映射或列表都不相等(即使結(jié)構(gòu)和內(nèi)容看起來相等)。 如果要避免這種情況,可以使用@PostLoad注釋來注釋一個(gè)方法,該方法可以在文檔加載后對(duì)JDK映射和列表執(zhí)行規(guī)范化。 我個(gè)人這樣做是為了確保始終看到MongoDB文檔的一致視圖,無論它們是從集合中提取還是尚未持久化。
參考: Carfey Software博客上的JCG合作伙伴提供的將MongoDB與Morphia結(jié)合使用的信息 。
相關(guān)文章 :
- Cassandra,MongoDB,CouchDB,Redis,Riak,HBase比較
- Java Code Geeks Andygene Web原型
- Java教程和Android教程列表
- 每個(gè)程序員或架構(gòu)師都應(yīng)該知道的9 + 7件事
翻譯自: https://www.javacodegeeks.com/2011/11/using-mongodb-with-morphia.html
總結(jié)
以上是生活随笔為你收集整理的将MongoDB与Morphia结合使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux系统命令行怎么打开(linux
- 下一篇: Java并发教程– CountDownL