Google App Engine for Java 第 3 部分持久性和关系.docx
- 文档编号:5004473
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:13
- 大小:22.12KB
Google App Engine for Java 第 3 部分持久性和关系.docx
《Google App Engine for Java 第 3 部分持久性和关系.docx》由会员分享,可在线阅读,更多相关《Google App Engine for Java 第 3 部分持久性和关系.docx(13页珍藏版)》请在冰豆网上搜索。
GoogleAppEngineforJava第3部分持久性和关系
GoogleAppEngineforJava,第3部分:
持久性和关系--基于Java的持久性和GoogleAppEngine数据存储
在企业环境中,数据持久性是交付可伸缩应用程序的基础。
RickHightower在他撰写的有关GoogleAppEngineforJava™的系列文章的最后一篇中,介绍了AppEngine当前基于Java的持久性框架。
让我们学习一些基础知识,了解为什么当前预览版中的Java持久性还未到发布的最佳时间,同时获得一个良好的演示,看看您如何在AppEngineforJava应用程序中保存数据。
注意,您将需要启动并运行来自第2部分的联系人管理应用程序,在此过程中学习如何使用JDOAPI保存、查询、更新和删除Contact对象。
AppEngineforJava力求为可伸缩的Web应用程序成功地编写一个持久层,可这个目标的达成情况又如何呢?
在本文中,我将概述AppEngineforJava的持久性框架,从而结束本系列文章。
该框架以JavaDataObjects(JDO)和JavaPersistenceAPI(JPA)为基础。
尽管在刚刚出现时前景良好,但是AppEngine的基于Java的持久性目前存在一些严重的缺陷,我将对此进行解释和演示。
您将学习AppEngineforJava持久性是如何运作以及有着哪些挑战,还将学习在使用面向Java开发人员的Google云平台时,您具有哪些持久性选择。
阅读本文并遍览这些示例时,您要牢记这样的事实:
现在的AppEngineforJava是一个预览版。
基于Java的持久性目前也许并不是您所希望或者需要的全部,可能并且应该会在未来发生变化。
现如今,使用AppEngineforJava进行可伸缩的、数据密集型的Java应用程序开发不合适胆小者或者保守派,这就是我在撰写本文时所学到的。
这更像跳入了游泳池的最深处:
看不到任何救生员,项目要沉下去还是往前游,取决于您自己。
注意,本文中的示例应用程序以第2部分中开发的联系人管理应用程序为基础。
您需要构建该应用程序,确保它是可运行的,这样才能继续学习本文的示例。
基础知识和抽象泄漏(leakyabstraction)
与原始的GoogleAppEngine一样,AppEngineforJava依靠Google的内部基础设施,实现可伸缩的应用程序开发的BigThree:
分布、复制和负载均衡。
由于使用的是Google基础设施,因此所有神奇的地方大都发生在后台,可以通过AppEngineforJava的基于标准的API获得。
数据存储接口是以JDO和JPA为基础的,而它们自身又是以开源的DataNucleus项目为基础。
AppEngineforJava还提供了一个低级别的适配器API,用来直接处理基于Google的BigTable实现的AppEngineforJava数据存储(要了解更多有关BigTable的信息,请参见第1部分)。
然而,AppEngineforJava数据持久性并不像纯GoogleAppEngine中的持久性那样简单。
由于BigTable不是一个关系数据库,JDO和JPA的接口出现了一些抽象泄漏。
例如,在AppEngineforJava中,您无法进行那些执行连接的查询。
您可以在JPA和JDO间设置关系,但它们只能用来持久化关系。
并且在持久化对象时,如果它们在相同的实体群中,那么它们只能被持久化到相同的原子事务中。
根据惯例,具有所有权的关系位于与父类相同的实体群中。
相反,不具有所有权的关系可以在不同的实体群中。
重新考虑数据规范化
要使用AppEngine的可伸缩的数据存储,需要重新考虑有关规范化数据的优点的教导。
当然,如果您在真实的环境中工作了足够长的时间,那么,您可能已经为了追求性能而牺牲过规范化了。
区别在于,在处理AppEngine数据存储时,您必须尽早且经常进行反规范化。
反规范化不再是一个忌讳的字眼,相反,它是一个设计工具,您可以把它应用在AppEngineforJava应用程序的许多方面。
当您尝试把为RDBMS编写的应用程序移植到AppEngineforJava时,AppEngineforJava的持久性泄漏的主要缺陷就会显露出来。
AppEngineforJava数据存储并不是关系数据库的临时替代物,因此,要把您对AppEngineforJava所做的工作移植到RDBMS端口并不容易。
采用现有的模式并把它移植到数据存储中,这种场景则更为少见。
如果您决定把一个遗留的Java企业应用程序移植到App引擎中,建议您要小心谨慎,并进行备份分析。
GoogleAppEngine是一个针对专门为它设计的应用程序的平台。
GoogleAppEngineforJava支持JDO和JPA,这使得这些应用程序能够被移植回更传统的、未进行规范化的企业应用程序。
关系的问题
AppEngineforJava目前的预览版的另外一个缺点是它对关系的处理。
为了创建关系,现在您必须对JDO使用AppEngineforJava特有的扩展。
假设键是在BigTable的工件的基础上生成—也就是说,“主键”将父对象键编码到其所有子键中—您将不得不在一个非关系数据库中管理数据。
另外一个限制是持久化数据。
如果您使用非标准的AppEngineforJavaKey类,事情将会变得复杂。
首先,把模型移植到RDBMS时,如何使用非标准Key?
其次,由于无法使用GWT引擎转换Key类,因此,任何使用这个类的模型对象都无法被作为GWT应用程序的一部分进行使用。
当然,撰写这篇文章时,GoogleAppEngineforJava还是纯粹的预览模式,没有到发布的最佳时间。
学习JDO中的关系文档(很少,而且包含一些不完整的示例)时,这点就变得显而易见了。
AppEngineforJava开发包提供了一系列的示例程序。
许多示例都使用JDO,没有一个使用JPA。
这些示例中没有一个示例(包括一个名为jdoexamples的示例)演示了关系,即使是简单的关系。
相反,所有的示例都只使用一个对象把数据保存到数据存储中。
GoogleAppEngineforJava讨论组充斥着有关如何使简单关系起作用的问题,但却鲜有答案。
很显然,有些开发人员有办法使其起作用,但是实现起来都很困难,而且遇到了一些复杂情况。
AppEngineforJava中的关系的底线是,无需从JDO或JPA获得大量支持就能够管理它们。
Google的BigTable是一种已经经过检验的技术,可用来生成可伸缩的应用程序,然而,您还可以在此基础上进行构建。
在BigTable上进行构建,您就不必处理还不完善的API层面。
另一方面,您只要处理一个较低级别的API。
AppEngineforJava中的JavaDataObjects
把传统的Java应用程序移植到AppEngineforJava中,甚至是给出关系挑战,这些可能都没有什么意义,然而,持久性场景还是存在的,这时使用这个平台就有意义了。
我将使用一个可行的示例来结束本文,您将体验AppEngineforJava持久性是如何工作的。
我们将以第2部分中建立的联系人管理应用程序为基础,介绍如何添加支持,以使用AppEngineforJava数据存储工具持久化Contact对象。
在前面的文章中,您创建了一个简单的GWTGUI,对Contact对象进行CRUD操作。
您定义了简单的接口,如清单1所示:
清单1.简单的ContactDAO接口
packagegaej.example.contact.server;
importjava.util.List;
importgaej.example.contact.client.Contact;
publicinterfaceContactDAO{
voidaddContact(Contactcontact);
voidremoveContact(Contactcontact);
voidupdateContact(Contactcontact);
List
}
接下来,创建一个模拟版本,与内存集合中的数据进行交互,如清单2所示:
清单2.模拟DAO的ContactDAOMock
packagegaej.example.contact.server;
importgaej.example.contact.client.Contact;
importjava.util.ArrayList;
importjava.util.Collections;
importjava.util.LinkedHashMap;
importjava.util.List;
importjava.util.Map;
publicclassContactDAOMockimplementsContactDAO{
Map
{
map.put("rhightower@",newContact("RickHightower",
"rhightower@","520-555-1212"));
map.put("scott@",newContact("ScottFauerbach",
"scott@","520-555-1213"));
map.put("bob@",newContact("BobDean",
"bob@","520-555-1214"));
}
publicvoidaddContact(Contactcontact){
Stringemail=contact.getEmail();
map.put(email,contact);
}
publicList
returnCollections.unmodifiableList(newArrayList
}
publicvoidremoveContact(Contactcontact){
map.remove(contact.getEmail());
}
publicvoidupdateContact(Contactcontact){
map.put(contact.getEmail(),contact);
}
}
现在,使用与GoogleAppEngine数据存储交互的应用程序替换模拟实现,看看会发生什么。
在这个示例中,您将使用JDO持久化Contact类。
使用GoogleEclipsePlugin编写的应用程序已经拥有了使用JDO所需的所有库。
它还包含了一个jdoconfig.xml文件,因此,一旦对Contact类进行了注释,您就已经准备好开始使用JDO。
清单3显示扩展后的ContactDAO接口,可使用JDOAPI进行持久化、查询、更新和删除对象:
清单3.使用JDO的ContactDAO
packagegaej.example.contact.server;
importgaej.example.contact.client.Contact;
importjava.util.List;
importjavax.jdo.JDOHelper;
importjavax.jdo.PersistenceManager;
importjavax.jdo.PersistenceManagerFactory;
publicclassContactJdoDAOimplementsContactDAO{
privatestaticfinalPersistenceManagerFactorypmfInstance=JDOHelper
.getPersistenceManagerFactory("transactions-optional");
publicstaticPersistenceManagerFactorygetPersistenceManagerFactory(){
returnpmfInstance;
}
publicvoidaddContact(Contactcontact){
PersistenceManagerpm=getPersistenceManagerFactory()
.getPersistenceManager();
try{
pm.makePersistent(contact);
}finally{
pm.close();
}
}
@SuppressWarnings("unchecked")
publicList
PersistenceManagerpm=getPersistenceManagerFactory()
.getPersistenceManager();
Stringquery="selectfrom"+Contact.class.getName();
return(List
}
publicvoidremoveContact(Contactcontact){
PersistenceManagerpm=getPersistenceManagerFactory()
.getPersistenceManager();
try{
pm.currentTransaction().begin();
//Wedon'thaveareferencetotheselectedProduct.
//Sowehavetolookitupfirst,
contact=pm.getObjectById(Contact.class,contact.getId());
pm.deletePersistent(contact);
pm.currentTransaction().commit();
}catch(Exceptionex){
pm.currentTransaction().rollback();
thrownewRuntimeException(ex);
}finally{
pm.close();
}
}
publicvoidupdateContact(Contactcontact){
PersistenceManagerpm=getPersistenceManagerFactory()
.getPersistenceManager();
Stringname=contact.getName();
Stringphone=contact.getPhone();
Stringemail=contact.getEmail();
try{
pm.currentTransaction().begin();
//Wedon'thaveareferencetotheselectedProduct.
//Sowehavetolookitupfirst,
contact=pm.getObjectById(Contact.class,contact.getId());
contact.setName(name);
contact.setPhone(phone);
contact.setEmail(email);
pm.makePersistent(contact);
pm.currentTransaction().commit();
}catch(Exceptionex){
pm.currentTransaction().rollback();
thrownewRuntimeException(ex);
}finally{
pm.close();
}
}
}
逐一比对方法
现在,考虑一下使用清单3中的每个方法时发生的情况。
您将会发现,方法的名字可能是新的,但它们的动作大部分情况下都应该感到熟悉。
首先,为了获取PersistenceManager,创建了一个静态的PersistenceManagerFactory。
如果您以前使用过JPA,PersistenceManager与JPA中的EntityManager很相似。
如果您使用过Hibernate,PersistenceManager与HibernateSession很相似。
基本上,PersistenceManager是JDO持久性系统的主接口。
它代表了与数据库的会话。
getPersistenceManagerFactory()方法返回静态初始化的PersistenceManagerFactory,如清单4所示:
清单4.getPersistenceManagerFactory()返回PersistenceManagerFactory
privatestaticfinalPersistenceManagerFactorypmfInstance=JDOHelper
.getPersistenceManagerFactory("transactions-optional");
publicstaticPersistenceManagerFactorygetPersistenceManagerFactory(){
returnpmfInstance;
}
addContact()方法把新的联系人添加到数据存储中。
为了做到这点,需要创建一个PersistenceManager实例,然后,调用PersistenceManager的makePersistence()方法。
makePersistence()方法采用临时的Contact对象(用户将在GWTGUI中填充),并且使其成为一个持久的对象。
所有这些如清单5所示:
清单5.addContact()
publicvoidaddContact(Contactcontact){
PersistenceManagerpm=getPersistenceManagerFactory()
.getPersistenceManager();
try{
pm.makePersistent(contact);
}finally{
pm.close();
}
}
注意在清单5中,persistenceManager是如何被封入在finally块中。
这确保能够把与persistenceManager关联的资源清除干净。
如清单6所示,listContact()方法从它所查找的persistenceManager中创建一个查询对象。
它调用了execute()方法,从数据存储中返回Contact列表。
清单6.listContact()
@SuppressWarnings("unchecked")
publicList
PersistenceManagerpm=getPersistenceManagerFactory()
.getPersistenceManager();
Stringquery="selectfrom"+Contact.class.getName();
return(List
}
在从数据存储中删除联系人之前,removeContact()通过ID查找联系人,如清单7所示。
它必须这么做,而不仅仅是把联系人直接删除,这是因为来自GWTGUI的Contact对JDO一无所知。
在删除前,您必须获得与PersistenceManager缓存关联的Contact。
清单7.removeContact()
publicvoidremoveContact(Contactcontact){
PersistenceManagerpm=getPersistenceManagerFactory()
.getPersistenceManager();
try{
pm.currentTransaction().begin();
//Wedon'thaveareferencetotheselectedProduct.
//Sowehavetolookitupfirst,
contact=pm.getObjectById(Contact.class,contact.getId());
pm.deletePersistent(contact);
pm.currentTransaction().commit();
}catch(Exceptionex){
pm.currentTransaction().rollback();
thrownewRuntimeException(ex);
}finally{
pm.close();
}
}
清单8中的updateContact()方法与removeContact()方法类似,用来查找Contact。
然后,updateCon
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Google App Engine for Java 部分持久性和关系 部分 持久性 关系
![提示](https://static.bdocx.com/images/bang_tan.gif)