value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/>
(3)设置数据读取策略和datastore调用期限。
AppEnginedatastore会复制所有的数据到多个存储位置,用以保证当其中一个出现故障时,datastore能迅速的切换到其他位置并正常的访问数据。
为了保证多个数据节点的一致性,应用程序会使用其中一个位置作为主位置(primarylocation),当主位置的数据更新时,其它位置的数据将被并行地改变。
在许多情况下,短时间内返回一些数据格式比等待返回当前数据更为重要,因此当主位置出现故障时,您可以让datastore从其它位置读取数据(可能数据不是最新的),这时就需要设置读取策略(readpolicy)。
Appengine提供两种策略:
strongconsistency和eventualconsistency,其默认策略是strongconsistency。
strongconsistency表示任何情况下都从主存储位置读取数据,而eventualconsistency则表示当主位置不可用时,可从其它存储位置读取数据。
其相应配置如下:
在默认情况下,对datastore的调用直到调用成功才会返回。
如果调用请求的期限到了,运行环境将会终止此次调用请求。
应用程序可以指定调用期限的具体时间,对于批量更新的请求,如果在提交过程中,限定的时间已到,那么到期之前的更新将会被持久化,而之后的更新将不会发生;对于一个事务处理,如果在事务提交过程中期限已到,那么整个事务将会回滚。
其相应的配置如下:
增强数据类
JDO使用一种后置编译处理的增强步骤来实现数据类与JDO实现之间的关联。
如果您使用Eclipse,GooglePluginforEclipse工具会自动完成这个步骤;如果您使用ApacheAnt,可以使用如下命令对已经编译出来的class文件进行增强处理。
java-cpclasspathcom.google.appengine.tools.enhancer.Enhanceclass-files
需要注意的是,Classpath必须包含appengine-tools-api.jar这个JAR包和所有的数据类文件。
获取PersistenceManager实例
应用程序与JDO进行交互是通过PersistenceManager类来实现的,您可以通过PersistenceManagerFactory来获取该类的实例。
由于PersistenceManagerFactory是根据JDO配置来构造的,较为耗时,因此,一个应用应该共享一个单一的实例。
我们可采用一个简单的单例模式类来对其进行封装,例如:
importjavax.jdo.JDOHelper;
importjavax.jdo.PersistenceManagerFactory;
publicfinalclassPMF{
privatestaticfinalPersistenceManagerFactorypmfInstance=
JDOHelper.getPersistenceManagerFactory("transactions-optional");
privatePMF(){}
publicstaticPersistenceManagerFactoryget(){
returnpmfInstance;
}
}
通过该工厂实例,就可以为每次的datastore访问请求创建PersistenceManager实例了,例如:
importjavax.jdo.PersistenceManager;
importjavax.jdo.PersistenceManagerFactory;
importPMF;
//...
PersistenceManagerpm=PMF.get().getPersistenceManager();
try{
//...dostuffwithpm...
}finally{
pm.close();
}
需要注意的是,在使用完PersistenceManager实例后,您需要调用close()方法,以确保不会在其它地方调用。
基于JDOAPI的CRUD
(1)要将简单数据对象存储到数据存储区中,可以调用PersistenceManager的makePersistent()方法,将实例传递给该方法。
对makePersistent()的调用时同步的,直到保存对象并更新索引后才会返回。
要在JDO中保存多个对象,可以使用makePersistentAll(...)方法。
(2)要获取对象,最简单、直接的方法就是通过键(key),利用PersistenceManager的getObjectById()方法来获取。
更加复杂的查询可通过JDO规范中的JDOQL来完成,例如通过lastName来查询Employee信息的查询可通过以下JDOQL完成。
Queryquery=pm.newQuery("selectfromEmployee"+
"wherelastName==lastNameParam"+
"parametersStringlastNameParam"+
"orderbyhireDatedesc");
Listresults=(List)query.execute("Smith");
(3)要将对象从数据存储区中删除,可以使用PersistenceManager的deletePersistent()方法。
(4)使用JDO更新对象的一种方式是抓取对象,然后在返回该对象的PersistenceManager仍然处于打开状态的情况下对该对象进行修改。
当关闭PersistenceManager时,修改部分会自动保留。
基于YAML描述文件以及bulkloader实现大批量结构化数据导入/导出
大批量数据导入,导出是常见的数据服务操作。
目前,对于AppEngineforJava的数据上传,还不是非常简便,需要以下四个步骤:
RemoteApiSelvlet的web.xml的例子。
(1)即使是AppEngineforJava,在批量数据下载和上传方面,还是依赖于AppEngineforPythonSDK的若干Python脚本,如bulkloader.py或是appcfg.py等等。
因而,用户还是需要安装AppEngineforPythonSDK在开发机上。
(2)在AppEngineforJava的google服务器端,需要部署com.google.apphosting.utils.remorteapi.RemorteApiServlet,该Servlet会与安装在AppEgnineforPythonSDK的开发机交互,来实现数据从开发机到服务器端的数据传输。
下面是一个部署RemoteApiSelvlet的web.xml的例子。
remoteapi
com.google.apphosting.utils.remoteapi.RemoteApiServlet
remoteapi
/remote_api
remoteapi
/remote_api
admin
(3)获取当前的AppEngineforJava服务器所用的数据表的Schema,写成yaml格式。
以下面的命令为例,该命令将所使用的DBschema全部下载到bulkloader.yaml内。
用户可以编辑该描述文件,上传后以实现对DBschema的修改。
appcfg.pycreate_bulkloader_config--filename=bulkloader.yaml
--urlhttp:
//
(4)下面是一个DBSchema的实例,该实例的含义是,数据表名为Person,主键是email,还包含属性name,surname,文件传输格式为CSV。
------------------------------------------------------------
transformers:
-kind:
Person
connector:
CSV
property_map:
-property:
__key__
external_name:
email
export_transform:
transform.key_id_or_name_as_string
-property:
name
external_name:
name
-property:
surname
external_name:
prenom
------------------------------------------------------------
(5)上述步骤完成以后,即可使用appcfg.py来实现数据的上传下载。
如下例所示,是用于包含实际数据的CSV文件。
appcfg.pydownload_data--config_file=bulkloader.yaml
--filename=
--kind=Person
--urlhttp:
//
appcfg.pyupload_data--config_file=bulkloader.yaml
--filename=
--kind=Person
--url
--batch_size=200
--num_threads=5
使用Blobstore实现非结构化数据存储
基于Web的数据应用常会遇到非结构化数据存储的需求,如文件、图片或视频的管理。
Appengine采用BlobstoreAPI来管理这些不易被datastore管理的大尺寸(总配额为2GB)数据对象(Blobs)。
一般来说,应用不会直接创建blobs数据,而是由提交的Web表单或者HTTPPOST请求间接创建的。
Blobs在创建之后能够被删除,但不能被修改。
每一个blob在datastore中都有相对应的记录信息,如创建时间、内容类型。
可通过blobkey来查询相关的记录和属性信息。
Blobstore的具体应用过程如下:
上传Blob
(1)编写上传JSP页面,并且设置blobstoreService.createUploadUrl()作为表单的action。
例如: