




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、數(shù)據(jù)模型的首次迭代接下來我們要開始完成我們的博客引擎的模型部分。JPA入門模型層是一個(gè)Play應(yīng)用的核心(對(duì)于其他Web框架也同樣成立)。它是一個(gè)對(duì)應(yīng)用操作的 資源的領(lǐng)域特定的表示。因?yàn)槲覀兿胍獎(jiǎng)?chuàng)建一個(gè)博客引擎,模型層就包括User,Post和Comme nt (用戶,博文和評(píng)論)。因?yàn)榇蠖鄶?shù)模型對(duì)象需要在應(yīng)用停止運(yùn)行時(shí)保留下來,我們需要把它們存儲(chǔ)在持久性數(shù)據(jù)庫中。一個(gè)普遍的選擇是使用關(guān)系型數(shù)據(jù)庫。因?yàn)镴ava是一個(gè)面向?qū)ο蟮恼Z言,我們將使用一個(gè)ORM來減少一些繁瑣的工作。JPA是一個(gè)給ORM定義一套標(biāo)準(zhǔn) API的Java規(guī)范。作為一個(gè) JPA的實(shí)現(xiàn),Play使用猿 媛皆知的Hibernate
2、框架。之所以使用 JPA而不是原生的 Hibernate API ,是因?yàn)檫@樣所有 的映射都可以用 Java對(duì)象直接完成。如果之前用過 Hibernate或JPA,你將驚訝于 Play所添加的包裝。不再需要配置什么了; JPA與Play框架合一。如果你不知道JPA,你可以在繼續(xù)之前閱讀一些JPA實(shí)現(xiàn)的介紹User 類我們首先來完成 User類。創(chuàng)建新文件/yabe/app/models/User.java,并寫入下面的內(nèi)容:package models;import java.util.*;import javax.persistenee.*;import play.db.jpa.*;En t
3、itypublic class User extendsModel public Stri ng email;public String password;public String full name;publicboolea n isAdmi n;public User (Stri ng email, String password, String full name) this .email = email;this.password=password;this.full name =full name;En tity 注解(anno tation )標(biāo)記該類成為托管的 JPA實(shí)體(ma
4、n aged JPA En tity ),而 Model父類將自動(dòng)提供一些接下來將會(huì)用到的有用的JPA輔助函數(shù)。這個(gè)類的所有成員變量都會(huì)被持久化到數(shù)據(jù)庫中。默認(rèn)情況下,對(duì)應(yīng)的表就是User。如果想要使用一個(gè)user是保留關(guān)鍵字的數(shù)據(jù)庫,你需要 給JPA映射指定一個(gè)不同的表名。要想這么做,使用Table(name=blog_user) 注解User類。你的模型對(duì)象不一定得繼承自 play.db.jpa.Model類。你也可以使用原生JPA。但繼承自該類往往是個(gè)更好的選擇,因?yàn)樗沟眠\(yùn)用JPA變得更為簡單。如果之前用過JPA,你知道每個(gè)JPA實(shí)體都需要提供一個(gè) ld屬性。在這里,Model父類 已
5、經(jīng)提供了一個(gè)自動(dòng)生成的ID,在大多數(shù)情況下,這樣就行了。不要認(rèn)為生成的id成員變量是函數(shù)變量 (functional identifier ),其實(shí)它是技術(shù)變量(technical identifier )。區(qū)分這兩概念通常是個(gè)好主意,記住自動(dòng)生成的ID是一個(gè)技術(shù)變量(譯注:這里我弄不懂,以下附上原文)Don t think about this provided id field as a functional identifier but as a technical identifier.It is gen erally a good idea to keep both con cept
6、s separated and to keep an automatically gen erated nu meric ID as a tech ni cal ide ntifier.如果你寫過Java ,心中可能已經(jīng)敲起了警鐘,因?yàn)槲覀兙尤淮罅渴褂霉谐蓡T!在Java (一如其他面向?qū)ο笳Z言),最佳實(shí)踐通常是盡量保持各成員私有,并提供getter和setter。這就是封裝,面向?qū)ο笤O(shè)計(jì)的基本概念之一。事實(shí)上,Play已經(jīng)考慮到這一點(diǎn),在自動(dòng)生成getter和setter的同時(shí)保持封裝;等下我們將看到它是怎么做到的。現(xiàn)在你可以刷新主頁面,看一下結(jié)果。當(dāng)然,除非你犯錯(cuò),否則應(yīng)該什么變化都看不到
7、:D。Play自動(dòng)編譯并加載了 User類,不過這沒有給應(yīng)用添加任何新特性。寫下第一個(gè)測(cè)試測(cè)試新增的User類的一個(gè)好方法是寫下JUnit測(cè)試用例。它會(huì)允許你增量開發(fā)的同時(shí)保證一切安好。要運(yùn)行一個(gè)測(cè)試用例,你需要在test模式下運(yùn)行應(yīng)用。 停止當(dāng)前正在運(yùn)行的應(yīng)用,打開命令行并輸入:yobe gumounet ploy test* Rtnoirifl in test He* CtrlC to stopT III I J C)Listening fcr traftsrrt m.socket at aMrest:錚鮒 17:14:1515I7lll5t72517:l+il5f6301?:1+:15,
8、3611 :M 15,83617 d*:15,631n;i+;L5.97ZD$ play testapplicati on.conf已經(jīng)存在一個(gè)默認(rèn)的BasicTests.java ,):importorg.j un it.*;importplay.test.*;importmodels.*;當(dāng)你在test mode 中運(yùn)行Play應(yīng)用時(shí),Play會(huì)自動(dòng)切換到test框架ID并加載對(duì)應(yīng)的 。閱讀框架ID文檔來了解更多。在瀏覽器打開http:/localhost:9000/tests頁面來看看測(cè)試運(yùn)行器。嘗試選擇所有的默認(rèn)測(cè)試并運(yùn)行;應(yīng)該全部都會(huì)是綠色但是默認(rèn)的測(cè)試其實(shí)什么都沒測(cè) :DTests
9、 runnertha tMU to mn then國tan andThere is 1 unit test.1 functional test.and 1 selenium test.我們將使用JUnit測(cè)試來測(cè)試模型部分。如你所見,所以讓我們打開它(/yabe/test/BasicTest.javaassertEquals(2, 1 + 1);publicclass BasicTest exte ndsUn itTestTest()public void aVeryImporta ntThi ngToTest刪除沒用的默認(rèn)測(cè)試(aVerylmporta ntTh in gToTest),創(chuàng)建
10、一個(gè)注冊(cè)新用戶并進(jìn)行檢查的測(cè)試:Testpublic void createA ndRetrieveUser() / Create a new user and save itnew User( bob , secret , Bob ).save();/ Retrieve the user with e-mail address bobUser bob = User.fi nd(byEmail , bob ).first();/ TestassertNotNull(bob);assertEquals( Bob , bob.fullname);如你所見,Model父類給我們提供了兩個(gè)非常有用的方
11、法:save()和find()。你可以在Play文檔中的JPA支持閱讀到Model類的更多方法。在test runner中選擇BasicTests.java,點(diǎn)擊開始,看一下是不是全都變綠了。我們將需要在User類中添加一個(gè)方法,來檢查給用戶的用戶名和密碼是否存在了。讓我們 完成它,并且測(cè)試它。在 User.java 中,添加 connect() 方法:public static User connect (String email, String password) retur n find(byEmailA ndPassword, email, password).first();如今測(cè)試
12、用例成這樣:Testpublic void tryC onn ectAsUser() / Create a new user and save itnew User( bob gmail .com , secret , Bob ).save();/ TestassertNotNull(User.connect (bob gmail .com , secret );assertNull(User.connect (bob gmail .com , badpassword );assertNull(User.connect (tom gmail .com , secret );每次修改之后,你都可
13、以從Play測(cè)試運(yùn)行器運(yùn)行所有的測(cè)試,來確保沒有什么被破壞了。Post 類Post類表示博客文章。讓我們寫下代碼: package models;import java.util.*;import javax.persistenee.*;import play.db.jpa.*;En titypublic class Post extends Model public String title;public Date postedAt;Lobpublic String content;Ma nyTo Onepublic User author;public Post (User author,
14、 String title, String content) this .author = author;this .title = title;this .content = content;this .postedAt = new Date();這里我們使用Lob注解告訴JPA來使用字符大對(duì)象類型(clob )來存儲(chǔ)文章內(nèi)容。我們也 聲明跟User類的關(guān)系是ManyToOne。這意味著每個(gè) Post對(duì)應(yīng)一個(gè)User,而每個(gè)User可 以有多個(gè)Post。PostgreSQL的最近版本不會(huì)將 Lob注解的String成員存儲(chǔ)成字符大對(duì)象類型,除非你額外用 Type(type = org.hib
15、ernate.type.TextType)注解該成員。我們將寫一個(gè)新的測(cè)試用例來檢查Post類能否正常工作。但在寫下更多測(cè)試之前,我們需要修改下JUnit測(cè)試類。在當(dāng)前測(cè)試中,數(shù)據(jù)庫的內(nèi)容永不刪除,所以每次運(yùn)行測(cè)試都會(huì)創(chuàng) 建越來越多的對(duì)象。假如將來我們需要測(cè)試對(duì)象的數(shù)目是否正確,這將會(huì)是一個(gè)問題。所以先寫一個(gè)JUnit的setup()方法在每次測(cè)試之前清空數(shù)據(jù)庫:public class BasicTestexte ndsUni tTest Beforepublic void setup () Fixtures.deleteDatabase();Before是JUnit測(cè)試工具的一個(gè)核心概念如
16、你所見,F(xiàn)ixtures類是一個(gè)在測(cè)試時(shí)幫助處理數(shù)據(jù)庫的類。再次運(yùn)行測(cè)試并檢查是否一切安好。之后接著下下一個(gè)測(cè)試:Testpublic void createPost () / Create a new user and save itUser bob = new User( bob , secret , Bob ).save();/ Create a new postnew Post(bob, My first post , Hello world ).save();/ Test that the post has bee n createdassertEquals( 1, Post.co
17、un t();/ Retrieve all posts created by Bob,bob).fetch();List bobPosts = Post.fi nd(byAuthor/ TestsassertEquals( 1, bobPosts.size();Post firstPost = bobPosts.get (0);assertNotNull(firstPost);assertEquals(bob, firstPost.author);assertEquals( My first post , firstPost.title);assertEquals( Hello world,
18、firstPost.c onten t);assertNotNull(firstPost.postedAt);不要忘記導(dǎo)入java.util.List,否則你會(huì)得到一個(gè)編譯錯(cuò)誤。添加Comment 類最后,我們需要給博文添加評(píng)論功能。創(chuàng)建Comment類的方式十分簡單直白。package models;import java.util.*;import javax.persistenee.*;import play.db.jpa.*;En titypublic classComment extendsModel public String author;public Date postedAt
19、;Lobpublic String content;Ma nyTo Onepublic Post post;publicComme nt(Post post, String author, Str ing content) this .post = post;this .author = author;this .content = content;this .postedAt = new Date();讓我們寫下第一個(gè)測(cè)試用例:Testpublic void postComments () / Create a new user and save itUser bob = new User(
20、 bob , secret , Bob ).save();/ Create a new postPost bobPost = new Post(bob, My first post , Hello world ).save ();/ Post a first comme ntNice post ).save();new Comme nt(bobPost,Jeffnew Comme nt(bobPost,Tom , I knew that !).save();/ Retrieve all comme ntsListvComme nt bobPostComme nts = Comme nt.fi
21、nd( etch();byPost , bobPost).f/ TestsassertEquals(2, bobPostComme nts.size();Comment firstComment = bobPostComments.get ( 0);assertNotNull(firstComme nt);assertEquals( Jeff, firstComme nt.author);assertEquals( Nice post , firstComme nt.c onten t); assertNotNull(firstComme nt.postedAt);Comme nt sec o
22、n dComme nt = bobPostComme nts.get ( 1);assertNotNull(sec on dComme nt);assertEquals( Tom , sec on dComme nt.author);assertEquals( I knew that !, sec on dComme nt.c onten t);assertNotNull(seco ndComme nt.postedAt);你可以看到Post和Comments 之間的聯(lián)系并不緊密:我們不得不通過查詢來獲得所有跟 某一個(gè)Post關(guān)聯(lián)的評(píng)論。通過在 Post和Comment類之間建立新的關(guān)系,我們
23、可以改善這 一點(diǎn)。在Post類添加comments成員:On eToMa ny( mappedBy=post , cascade=CascadeType.ALL)public List comme nts;public Post (User author, String title, String content) this .comments =new ArrayListvComment();this .author = author;this .title = title;this .content = content;this .postedAt = new Date();注意現(xiàn)在我們用
24、 mappedBy屬性來告訴JPA Comment類的post成員是維持這個(gè)關(guān)系的一方。 當(dāng)你用JPA定義一個(gè)雙向關(guān)系時(shí),需要指定哪一方來維持這個(gè)關(guān)系。在這個(gè)例子中,因?yàn)?Comment示例依賴于 Post,我們按 Comment.post 的反向來定義關(guān)系。我們也設(shè)置了 cascade屬性來告訴JPA,我們希望Post的刪除將級(jí)聯(lián)影響到 comments。 也即是,如果你刪除一個(gè)博文時(shí),所有相關(guān)的評(píng)論也將一并刪除。由于有了這個(gè)新關(guān)系,我們可以給Post類添加一個(gè)輔助方法來簡化評(píng)論的添加:public Post addComme nt(Stri ng author, Str ing conte
25、nt) Comment newComment =new Comment( this , author, content).save();this .comments.add(newComment);this .save();return this ;讓我們寫多一個(gè)測(cè)試檢查它能否工作:Testpublic void useTheComme ntsRelati on() / Create a new user and save itUser bob = new User( bob , secret , Bob ).save();/ Create a new post).savePost bobPo
26、st = new Post(bob, My first post , Hello world();/ Post a first comme ntbobPost.addComment(Jeff , Nice post );bobPost.addComment(Tom , I knew that !);/ Count thi ngsassertEquals(1, User.co un t();assertEquals(2, Comme nt.co un t();/ Retrieve Bobs postbobPost = Post.fi nd(byAuthor , bob).first();asse
27、rtNotNull(bobPost);/ Navigate to comme ntsassertEquals(2, bobPme nts.size();assertEquals(Jeff , bobPments.get (0).author);/ Delete the postbobPost.delete();/ Check that all comme nts have bee n deleted1, User.co un t();0, Post.cou nt();0, Comme nt.co un t();assertEquals(assertEquals(assertEquals(這次全
28、綠了么?Tests runnerSelKl tiw *m1s to run fwi dick 沁可 and 阿町ruThere is 1 unit test,使用Fixtures來寫更復(fù)雜的測(cè)試當(dāng)你開始寫更加復(fù)雜的測(cè)試,你通常需要一些測(cè)試數(shù)據(jù)。Fixtures允許你在一個(gè)YAML文件 中描述你的模型,并在測(cè)試開始前加載。編輯 /yabe/test/data.yml并開始描述一個(gè) User:User(bob):email : bobpassword : secretfull name : Bob呃,因?yàn)閐ata.yml有點(diǎn)大,你可以在 這里下載它。現(xiàn)在我們可以創(chuàng)建一個(gè)加載數(shù)據(jù)并對(duì)它運(yùn)行一些斷言的
29、測(cè)試用例:Testpublic void fullTest () Fixtures .lo adModels(data.yml);/ Count thi ngsassertEquals(assertEquals(assertEquals(2, User.co un t();3, Post.cou nt();3, Comme nt.co un t();/ Try to connect as users assertNotNull(User.c onn ect( assertNotNull(User.c onn ect( assertNull(User.c onn ect( assertNull(
30、User.c onn ect(bob , secret );jeff , secret );jeffbadpassword);tom , secret );/ Find all of Bobs postsList bobPosts = Post.find( fetch();assertEquals( 2, bobPosts.size();author.email , bob)./ Fi nd all comme nts related to Bobs postsList bobComme nts = Comme nt.fi nd( b ).fetch();assertEquals( 3, bobComme nts.size();post.author.emailbo/ Find the most rece nt postPost fron tPost = Post.fi nd(order by postedAt desc).first();assertNotNull(fro ntPost);assertEquals( About the model layer ,
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025鋼結(jié)構(gòu)施工合同范文
- 預(yù)定合同定金協(xié)議書范本
- 藝術(shù)機(jī)構(gòu)收購合同協(xié)議書
- 學(xué)校蔬菜供貨合同協(xié)議書
- 股權(quán)眾籌合同協(xié)議書范本
- 字音考試題及答案
- 2025-2030中國重質(zhì)純堿行業(yè)發(fā)展趨勢(shì)及投資風(fēng)險(xiǎn)分析研究報(bào)告
- 商法入門試題及答案
- 2025-2030中國遠(yuǎn)洋捕撈行業(yè)市場發(fā)展分析與投資前景預(yù)測(cè)報(bào)告
- 買賣銑刀合同協(xié)議書模板
- 學(xué)校特色課程實(shí)施方案
- 【MOOC】創(chuàng)新思維與創(chuàng)業(yè)實(shí)驗(yàn)-東南大學(xué) 中國大學(xué)慕課MOOC答案
- 企業(yè)環(huán)境信息披露評(píng)價(jià)研究的國內(nèi)外文獻(xiàn)綜述6400字
- 2024年秋兒童發(fā)展問題的咨詢與輔導(dǎo)終考期末大作業(yè)案例分析1-5答案
- 創(chuàng)新思維及設(shè)計(jì)方法學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 湖南省建筑工程消耗量標(biāo)準(zhǔn)裝飾定額
- 肺栓塞的診斷和治療 課件
- 劍橋KET口語題庫(含滿分答案)
- 小學(xué)教育教學(xué)案例范文【5篇】
- 玻璃鋼防腐工程合同范本
- TSG ZF001-2006《安全閥安全技術(shù)監(jiān)察規(guī)程》
評(píng)論
0/150
提交評(píng)論