Morphia官方文檔翻譯(一)Quick Tour

Morphia官方文檔翻譯(一)Quick Tour

原文鏈接:https://mongodb.github.io/morphia/1.2/getting-started/quick-tour/

快速指南

Morphia封裝了MongoDB Java driver,所以熟悉driver會(huì)有所幫助。Morphia 已經(jīng)盡了最大努力去從driver中抽象出來(lái),但是如果遇到疑惑不解的問(wèn)題,請(qǐng)同時(shí)參考java driver文檔。
以下代碼片段來(lái)自theQuickTour.java,點(diǎn)擊獲取 Morphia source。

設(shè)置Morphia

下面的例子展示了如何創(chuàng)建Morphia實(shí)例。使用該實(shí)例,你可以對(duì)Morphia如何進(jìn)行entities映射和提交查詢做配置。

final Morphia morphia = new Morphia();
// tell Morphia where to find your classes
// can be called multiple times with different packages or classes
morphia.mapPackage("org.mongodb.morphia.example");
// create the Datastore connecting to the default port on the local host
final Datastore datastore = morphia.createDatastore(new MongoClient(), "morphia_example");
datastore.ensureIndexes();

這段代碼創(chuàng)建了我們例子程序?qū)⒂玫降腗orphia實(shí)例。Morphia類可以配置Mapper和一些系統(tǒng)范圍的選項(xiàng),也負(fù)責(zé)創(chuàng)建Datastore。Datastore有兩個(gè)參數(shù):MongoClient和數(shù)據(jù)庫(kù)的名字。通過(guò)創(chuàng)建不同的Datastore,我們可以只配置Morphia一次,但連接不同的數(shù)據(jù)庫(kù),實(shí)際應(yīng)用中,這種情況不常見(jiàn),但有可能存在。

被我們跳過(guò)的第二行,值得更進(jìn)一步說(shuō)明。在這個(gè)例子中,我們告訴Morphia搜索指定的包,找到每一個(gè)@Entity(后續(xù)說(shuō)明這個(gè)注解)注解的類,進(jìn)一步發(fā)現(xiàn)要映射的元數(shù)據(jù)(metadata )。有幾種不同的映射并且可以多次調(diào)用,以便覆蓋你所有的entities。

映射選項(xiàng)(Mapping Options)

創(chuàng)建Morphia實(shí)例后,可以通過(guò)MappingOptions類配置映射選項(xiàng)。雖然在創(chuàng)建Morphia實(shí)例的時(shí)候也可以指定Mapper,但大部分人會(huì)使用默認(rèn)的mapper。不管哪種情況,都可以通過(guò)Morphia實(shí)例的getMapper()方法獲取Mapper。最常用的兩個(gè)選項(xiàng)是storeEmpties和storeNulls。默認(rèn)情況下,Morphia不會(huì)存儲(chǔ)空List或Map,也不會(huì)存儲(chǔ)null值到MongoDB上。如果你的應(yīng)用需要用到empty or null 值,需設(shè)置相應(yīng)的選項(xiàng)為true。還有一些其他的配置選項(xiàng),在這兒不會(huì)提到。

映射類(Mapping Classes)

Morphia處理你的類有兩種方式:上層的entities或嵌入式的entities(as top level entities or embedded in others)。任何@Entity注解標(biāo)注的類都會(huì)被視為上層entities,直接對(duì)應(yīng)MongoDB中的collection的document。任何@Entity注解標(biāo)注的類必須有一個(gè)@Id注解的字段,對(duì)應(yīng)MongoDB的document的_id。@Embedded表示這個(gè)類是嵌入式的文檔,不要求有@Id注解的字段。

@Entity("employees")
@Indexes( @Index(value = "salary", fields = @Field("salary")))
class Employee { 
@Id 
private ObjectId id; 
private String name;
@Reference 
private Employee manager; 
@Reference
private List<Employee> directReports; 
@Property("wage") 
private Double salary;}

@Entity注解里有個(gè)"employees",默認(rèn)情況下Morphia使用類名作集合名,如果傳入了字符串,就會(huì)使用這個(gè)字符串作集合名。更多注解的細(xì)節(jié)請(qǐng)查閱annotations guide
@Indexes注解列出了Morphia將創(chuàng)建哪些索引,在這個(gè)例子中,我們?cè)谧侄蝧alary上定義了一個(gè)名為salary的索引,默認(rèn)升序。更多信息在這里
我們標(biāo)記了id字段為我們的主鍵(document的_id字段),ID的類型為Java driver的ObjectId類型。ID可以是任何類型,但通常是ObjectId或Long類型。需要指出的是,Morphia將嘗試拷貝每一個(gè)字段到數(shù)據(jù)庫(kù)中,而不是transient and static。
@Property注解是一個(gè)可選項(xiàng),如果不使用這個(gè)注解,Morphia會(huì)使用Java字段名做document的字段名,使用@Property注解可以指定document的字段名。
@Reference告訴Morphia這個(gè)字段引用了另外的Morphia mapped entities。在這種情況下,Morphia會(huì)按照MongoDB中DBRef 的方式存儲(chǔ),其實(shí)就是集合名和鍵值。這些引用的entities必須已經(jīng)存儲(chǔ)了或者至少已分配了ID,否則Morphia會(huì)拋出異常。

存儲(chǔ)數(shù)據(jù)(Saving Data)

像平常使用Java對(duì)象一樣使用:

final Employee elmer = new Employee("Elmer Fudd", 50000.0);
datastore.save(elmer);

更進(jìn)一步,定義一些關(guān)系并存儲(chǔ):

final Employee daffy = new Employee("Daffy Duck", 40000.0);
datastore.save(daffy);
final Employee pepe = new Employee("Pepé Le Pew", 25000.0);
datastore.save(pepe);
elmer.getDirectReports().add(daffy);
elmer.getDirectReports().add(pepe);
datastore.save(elmer);

正如你所看到的,我們只需要?jiǎng)?chuàng)建和保存其他Employees,然后就可以添加他們到direct reports鏈表并保存。Morphia負(fù)責(zé)保存Daffy and Pepé相關(guān)的keys到Elmer’s document。更新MongoDB中的數(shù)據(jù)就像更新你的Java對(duì)象一樣簡(jiǎn)單,最后記著調(diào)用datastore.save()。對(duì)于大量的更新(比如每個(gè)人都晉升了),這不是最有效的更新方式。在不拉取每個(gè)document的前提下直接更新數(shù)據(jù)庫(kù)的數(shù)據(jù)是有可能的,轉(zhuǎn)換成Java對(duì)象,更新,轉(zhuǎn)換回document,然后寫(xiě)入MongoDB.在展示這個(gè)機(jī)制之前,先要看看怎么查詢。

查詢(Querying)

Morphia嘗試使你的查詢盡可能類型安全。轉(zhuǎn)換你數(shù)據(jù)的所有細(xì)節(jié)都直接被Morphia處理了,幾乎沒(méi)有什么額外的操作需要你來(lái)進(jìn)行。

final Query<Employee> query = datastore.createQuery(Employee.class);
final List<Employee> employees = query.asList();

這是一個(gè)簡(jiǎn)單的Morphia查詢。我們讓Datastore創(chuàng)建一個(gè)Employee類型的查詢,把查到Employee存到List中。對(duì)于很大的查詢結(jié)果,這很可能導(dǎo)致內(nèi)存不足。在這個(gè)簡(jiǎn)單的例子中使用了asList(),但實(shí)際上,fetch()是更合適的選擇。大多數(shù)查詢都會(huì)以某種方式過(guò)濾數(shù)據(jù),有兩種方式實(shí)現(xiàn):

underpaid = datastore.createQuery(Employee.class) 
                     .field("salary")
                     .lessThanOrEq(30000) .asList();

field()方法用來(lái)過(guò)濾字段并且返回一個(gè)接口的實(shí)例,這個(gè)接口含有一組用于構(gòu)建查詢的方法。這種方式是有益的,編譯時(shí)檢查是必要的。這種查詢構(gòu)建的方式對(duì)于避免javac因缺失方法失敗和輔助IDE的自動(dòng)完成都很有用。
另一種使用filter()方法的途徑比f(wàn)ield()更加自由和簡(jiǎn)潔。我們可以直接嵌入操作符到查詢字符串中。雖然這種方式?jīng)]有那么繁冗,它確實(shí)放了更多的東西到字符串中來(lái)驗(yàn)證并有可能出錯(cuò):

List<Employee> underpaid = datastore.createQuery(Employee.class) 
                                    .filter("salary <=", 30000)
                                    .asList();

更新(Updates)

掌握了查詢之后,我們可以回到in-database更新的問(wèn)題。這類更新包含兩個(gè)組件:一個(gè)查詢,一系列更新操作。在這個(gè)例子中,我們找出所有領(lǐng)取薪酬的員工,給他們加薪10000。第一步是創(chuàng)建查詢找出領(lǐng)取薪酬的員工,這段代碼我們之前已見(jiàn)到過(guò):

final Query<Employee> underPaidQuery = datastore.createQuery(Employee.class) 
                                                .filter("salary <=", 30000);

To define how we want to update the documents matched by this query, we create an UpdateOperations instance:
為了定義我們?nèi)绾胃耫ocuments,我們先創(chuàng)建一個(gè)UpdateOperations 實(shí)例:

final UpdateOperations<Employee> updateOperations = datastore.createUpdateOperations(Employee.class)
                                                             .inc("salary", 10000);

這個(gè)類有很多種操作,但在這個(gè)例子中,我們只更新salary字段(增加10000),用到了$inc
operator。最后一步:
final UpdateResults results = datastore.update(underPaidQuery, updateOperations);
這行代碼執(zhí)行了數(shù)據(jù)庫(kù)內(nèi)的update,沒(méi)有拉取documents。UpdateResults實(shí)例返回一系列更新操作的統(tǒng)計(jì)數(shù)據(jù)。

刪除(Removes)

final Query<Employee> overPaidQuery = datastore.createQuery(Employee.class) 
                                               .filter("salary >", 100000);
datastore.delete(overPaidQuery);

delete()有一些其他的用法,但這就是最普通的用法。如果你手上已經(jīng)有了一個(gè)對(duì)象,有一個(gè)delete可以取得引用并刪除它。更多信息請(qǐng)參考javadoc

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 官方原文地址 Room持久化庫(kù) Room為SQLite提供一個(gè)抽象層,在充分利用SQLite的同時(shí),允許流暢的數(shù)據(jù)...
    咸魚(yú)Jay閱讀 1,876評(píng)論 0 6
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,253評(píng)論 6 342
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,725評(píng)論 25 709
  • 王二喜家發(fā)了,真地發(fā)了,一夜之間就發(fā)了似的。 王二喜,三十來(lái)歲,是一個(gè)技術(shù)工人,在村里幫當(dāng)?shù)氐睦习彘_(kāi)開(kāi)挖掘機(jī),收入...
    晨溪一縷陽(yáng)光閱讀 1,929評(píng)論 17 12
  • 王曉梅,聽(tīng)從自己內(nèi)心的聲音。
    沙漏記得閱讀 119評(píng)論 0 0

友情鏈接更多精彩內(nèi)容