Play框架1.2.7版本教程(2)---数据模型的首次迭代Word版

上传人:每**** 文档编号:50898992 上传时间:2022-01-23 格式:DOC 页数:18 大小:237.50KB
收藏 版权申诉 举报 下载
Play框架1.2.7版本教程(2)---数据模型的首次迭代Word版_第1页
第1页 / 共18页
Play框架1.2.7版本教程(2)---数据模型的首次迭代Word版_第2页
第2页 / 共18页
Play框架1.2.7版本教程(2)---数据模型的首次迭代Word版_第3页
第3页 / 共18页
资源描述:

《Play框架1.2.7版本教程(2)---数据模型的首次迭代Word版》由会员分享,可在线阅读,更多相关《Play框架1.2.7版本教程(2)---数据模型的首次迭代Word版(18页珍藏版)》请在装配图网上搜索。

1、数据模型的首次迭代接下来我们要开始完成我们的博客引擎的模型部分。JPA入门模型层是一个Play应用的核心(对于其他Web框架也同样成立)。它是一个对应用操作的资源的领域特定的表示。因为我们想要创建一个博客引擎,模型层就包括User,Post和Comment(用户,博文和评论)。因为大多数模型对象需要在应用停止运行时保留下来,我们需要把它们存储在持久性数据库中。一个普遍的选择是使用关系型数据库。因为Java是一个面向对象的语言,我们将使用一个ORM来减少一些繁琐的工作。JPA是一个给ORM定义一套标准API的Java规范。作为一个JPA的实现,Play使用猿媛皆知的Hibernate框架。之所以

2、使用JPA而不是原生的Hibernate API,是因为这样所有的映射都可以用Java对象直接完成。如果之前用过Hibernate或JPA,你将惊讶于Play所添加的包装。不再需要配置什么了;JPA与Play框架合一。如果你不知道JPA,你可以在继续之前阅读一些JPA实现的介绍User类我们首先来完成User类。创建新文件/yabe/app/models/User.java,并写入下面的内容:package models;import java.util.*;import javax.persistence.*;import play.db.jpa.*;Entitypublic class U

3、ser extends Model public String email; public String password; public String fullname; public boolean isAdmin; public User(String email, String password, String fullname) this.email = email; this.password = password; this.fullname = fullname; Entity注解(annotation)标记该类成为托管的JPA实体(managed JPA Entity),而M

4、odel父类将自动提供一些接下来将会用到的有用的JPA辅助函数。这个类的所有成员变量都会被持久化到数据库中。默认情况下,对应的表就是User。如果想要使用一个user是保留关键字的数据库,你需要给JPA映射指定一个不同的表名。要想这么做,使用Table(name=blog_user)注解User类。你的模型对象不一定得继承自play.db.jpa.Model类。你也可以使用原生JPA。但继承自该类往往是个更好的选择,因为它使得运用JPA变得更为简单。如果之前用过JPA,你知道每个JPA实体都需要提供一个Id属性。在这里,Model父类已经提供了一个自动生成的ID,在大多数情况下,这样就行了。不

5、要认为生成的id成员变量是函数变量(functional identifier),其实它是技术变量(technical identifier)。区分这两概念通常是个好主意,记住自动生成的ID是一个技术变量(译注:这里我弄不懂,以下附上原文)Dont think about this providedidfield as a functional identifier but as a technical identifier. It is generally a good idea to keep both concepts separated and to keep an automatic

6、ally generated numeric ID as a technical identifier.如果你写过Java,心中可能已经敲起了警钟,因为我们居然大量使用公有成员!在Java(一如其他面向对象语言),最佳实践通常是尽量保持各成员私有,并提供getter和setter。这就是封装,面向对象设计的基本概念之一。事实上,Play已经考虑到这一点,在自动生成getter和setter的同时保持封装;等下我们将看到它是怎么做到的。现在你可以刷新主页面,看一下结果。当然,除非你犯错,否则应该什么变化都看不到:D。Play自动编译并加载了User类,不过这没有给应用添加任何新特性。写下第一个测

7、试测试新增的User类的一个好方法是写下JUnit测试用例。它会允许你增量开发的同时保证一切安好。要运行一个测试用例,你需要在test模式下运行应用。停止当前正在运行的应用,打开命令行并输入:$ play testplay test命令就像play run,不过它加载的是一个测试运行器模块,使得你可以直接在浏览器中运行测试套件。当你在test mode中运行Play应用时,Play会自动切换到test框架ID并加载对应的application.conf。阅读框架ID文档来了解更多。在浏览器打开http:/localhost:9000/tests页面来看看测试运行器。尝试选择所有的默认测试并运行

8、;应该全部都会是绿色但是默认的测试其实什么都没测:D我们将使用JUnit测试来测试模型部分。如你所见,已经存在一个默认的BasicTests.java,所以让我们打开它(/yabe/test/BasicTest.java):import org.junit.*;import play.test.*;import models.*;public class BasicTest extends UnitTest Test public void aVeryImportantThingToTest() assertEquals(2, 1 + 1); 删除没用的默认测试(aVeryImportantT

9、hingToTest),创建一个注册新用户并进行检查的测试:Testpublic void createAndRetrieveUser() / Create a new user and save it new User(bob, secret, Bob).save(); / Retrieve the user with e-mail address bob User bob = User.find(byEmail, bob).first(); / Test assertNotNull(bob); assertEquals(Bob, bob.fullname);如你所见,Model父类给我们提

10、供了两个非常有用的方法:save()和find()。你可以在Play文档中的JPA支持阅读到Model类的更多方法。在test runner中选择BasicTests.java,点击开始,看一下是不是全都变绿了。我们将需要在User类中添加一个方法,来检查给用户的用户名和密码是否存在了。让我们完成它,并且测试它。在User.java中,添加connect()方法:public static User connect(String email, String password) return find(byEmailAndPassword, email, password).first();如今

11、测试用例成这样:Testpublic void tryConnectAsUser() / Create a new user and save it new User(bob, secret, Bob).save(); / Test assertNotNull(User.connect(bob, secret); assertNull(User.connect(bob, badpassword); assertNull(User.connect(tom, secret);每次修改之后,你都可以从Play测试运行器运行所有的测试,来确保没有什么被破坏了。Post类Post类表示博客文章。让我们写

12、下代码:package models;import java.util.*;import javax.persistence.*;import play.db.jpa.*;Entitypublic class Post extends Model public String title; public Date postedAt; Lob public String content; ManyToOne public User author; public Post(User author, String title, String content) this.author = author;

13、 this.title = title; this.content = content; this.postedAt = new Date(); 这里我们使用Lob注解告诉JPA来使用字符大对象类型(clob)来存储文章内容。我们也声明跟User类的关系是ManyToOne。这意味着每个Post对应一个User,而每个User可以有多个Post。PostgreSQL的最近版本不会将Lob注解的String成员存储成字符大对象类型,除非你额外用Type(type = org.hibernate.type.TextType)注解该成员。我们将写一个新的测试用例来检查Post类能否正常工作。但在写下

14、更多测试之前,我们需要修改下JUnit测试类。在当前测试中,数据库的内容永不删除,所以每次运行测试都会创建越来越多的对象。假如将来我们需要测试对象的数目是否正确,这将会是一个问题。所以先写一个JUnit的setup()方法在每次测试之前清空数据库:public class BasicTest extends UnitTest Before public void setup() Fixtures.deleteDatabase(); Before是JUnit测试工具的一个核心概念如你所见,Fixtures类是一个在测试时帮助处理数据库的类。再次运行测试并检查是否一切安好。之后接着下下一个测试:T

15、estpublic void createPost() / Create a new user and save it User bob = new User(bob, secret, Bob).save(); / Create a new post new Post(bob, My first post, Hello world).save(); / Test that the post has been created assertEquals(1, Post.count(); / Retrieve all posts created by Bob List bobPosts = Post

16、.find(byAuthor, bob).fetch(); / Tests assertEquals(1, bobPosts.size(); Post firstPost = bobPosts.get(0); assertNotNull(firstPost); assertEquals(bob, firstPost.author); assertEquals(My first post, firstPost.title); assertEquals(Hello world, firstPost.content); assertNotNull(firstPost.postedAt);不要忘记导入

17、java.util.List,否则你会得到一个编译错误。添加Comment类最后,我们需要给博文添加评论功能。创建Comment类的方式十分简单直白。package models;import java.util.*;import javax.persistence.*;import play.db.jpa.*;Entitypublic class Comment extends Model public String author; public Date postedAt; Lob public String content; ManyToOne public Post post; pub

18、lic Comment(Post post, String author, String content) this.post = post; this.author = author; this.content = content; this.postedAt = new Date(); 让我们写下第一个测试用例:Testpublic void postComments() / Create a new user and save it User bob = new User(bob, secret, Bob).save(); / Create a new post Post bobPost

19、 = new Post(bob, My first post, Hello world).save(); / Post a first comment new Comment(bobPost, Jeff, Nice post).save(); new Comment(bobPost, Tom, I knew that !).save(); / Retrieve all comments List bobPostComments = Comment.find(byPost, bobPost).fetch(); / Tests assertEquals(2, bobPostComments.siz

20、e(); Comment firstComment = bobPostComments.get(0); assertNotNull(firstComment); assertEquals(Jeff, firstComment.author); assertEquals(Nice post, firstComment.content); assertNotNull(firstComment.postedAt); Comment secondComment = bobPostComments.get(1); assertNotNull(secondComment); assertEquals(To

21、m, secondComment.author); assertEquals(I knew that !, secondComment.content); assertNotNull(secondComment.postedAt);你可以看到Post和Comments之间的联系并不紧密:我们不得不通过查询来获得所有跟某一个Post关联的评论。通过在Post和Comment类之间建立新的关系,我们可以改善这一点。在Post类添加comments成员:.OneToMany(mappedBy=post, cascade=CascadeType.ALL)public List comments;pub

22、lic Post(User author, String title, String content) ments = new ArrayList(); this.author = author; this.title = title; this.content = content; this.postedAt = new Date();.注意现在我们用mappedBy属性来告诉JPAComment类的post成员是维持这个关系的一方。当你用JPA定义一个双向关系时,需要指定哪一方来维持这个关系。在这个例子中,因为Comment示例依赖于Post,我们按Comment.post的反向来定义关系

23、。我们也设置了cascade属性来告诉JPA,我们希望Post的删除将级联影响到comments。也即是,如果你删除一个博文时,所有相关的评论也将一并删除。由于有了这个新关系,我们可以给Post类添加一个辅助方法来简化评论的添加:public Post addComment(String author, String content) Comment newComment = new Comment(this, author, content).save(); ments.add(newComment); this.save(); return this;让我们写多一个测试检查它能否工作:Te

24、stpublic void useTheCommentsRelation() / Create a new user and save it User bob = new User(bob, secret, Bob).save(); / Create a new post Post bobPost = new Post(bob, My first post, Hello world).save(); / Post a first comment bobPost.addComment(Jeff, Nice post); bobPost.addComment(Tom, I knew that !)

25、; / Count things assertEquals(1, User.count(); assertEquals(1, Post.count(); assertEquals(2, Comment.count(); / Retrieve Bobs post bobPost = Post.find(byAuthor, bob).first(); assertNotNull(bobPost); / Navigate to comments assertEquals(2, bobPments.size(); assertEquals(Jeff, bobPments.get(0).author);

26、 / Delete the post bobPost.delete(); / Check that all comments have been deleted assertEquals(1, User.count(); assertEquals(0, Post.count(); assertEquals(0, Comment.count();这次全绿了么?使用Fixtures来写更复杂的测试当你开始写更加复杂的测试,你通常需要一些测试数据。Fixtures允许你在一个YAML文件中描述你的模型,并在测试开始前加载。编辑/yabe/test/data.yml并开始描述一个User:User(b

27、ob): email: bob password: secret fullname: Bob.呃,因为data.yml有点大,你可以在这里下载它。现在我们可以创建一个加载数据并对它运行一些断言的测试用例:Testpublic void fullTest() Fixtures.loadModels(data.yml); / Count things assertEquals(2, User.count(); assertEquals(3, Post.count(); assertEquals(3, Comment.count(); / Try to connect as users assert

28、NotNull(User.connect(bob, secret); assertNotNull(User.connect(jeff, secret); assertNull(User.connect(jeff, badpassword); assertNull(User.connect(tom, secret); / Find all of Bobs posts List bobPosts = Post.find(author.email, bob).fetch(); assertEquals(2, bobPosts.size(); / Find all comments related t

29、o Bobs posts List bobComments = Comment.find(post.author.email, bob).fetch(); assertEquals(3, bobComments.size(); / Find the most recent post Post frontPost = Post.find(order by postedAt desc).first(); assertNotNull(frontPost); assertEquals(About the model layer, frontPost.title); / Check that this

30、post has two comments assertEquals(2, frontPments.size(); / Post a new comment frontPost.addComment(Jim, Hello guys); assertEquals(3, frontPments.size(); assertEquals(4, Comment.count();你可以在YAML manual page中阅读更多关于Play和YAML的内容。保存你的成果现在我们已经完成了博客引擎的大部分模型层。既然已经创建并测试好了模型层,我们可以开始开发这个Web应用了。不过在继续前进之前,是时候用Bazaar保存你的成果。打开命令行,输入bzr st来看看在前一个提交之后做的修改:$ bzr st如你所见,一些新文件不在版本控制之中。test-result目录不需要加入到版本控制,所以就忽略它。$ bzr ignore test-result通过bzr add向版本控制加入其他文件。$ bzr add你现在可以提交你的改动了。$ bzr commit -m The model layer is ready推荐精选

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!