Google App Engine开发指南【第二章】数据操作(一)


上一章讲解了Google App Engine的开发环境搭建以及一些基本的知识点,本章开始讲解Google App Engine中对数据的CURD操作。对数据的CURD操作是任何一个系统中最基本也是最繁琐的内容。在学习本章内容的过程中,你可以思考自己在普通的项目中是如何对数据库进行操作,以之对比方可更快的掌握。


Google App Engine提供了以下三种数据存储方案:
  • App Engine Datastore 
    App Engine Datastore是Google推荐使用的,同时也是非常优秀的NoSQL对象型数据存储方案,和业界流行的NoSQL数据库一样,它拥有自己的查询引擎并提供了对事物的支持。你可以完全抛开传统的“对象-关系”型数据库思维。这种模式下,将数据库看成是一个很大的虚拟仓库,将数据看作一个个的对象处理。所有对数据的操作都将通过数据仓库提供的api实现,如:put、get、 delete、query等方法。
  • Google Cloud SQL 
    Google Cloud SQL是存活在GoogleAppEngine上的MySQL数据库。它提供了和MySQL高度类似的操作方式,当然由于平台限制,MySQL中也有部分功能不能提供。除此之外,它就是一个Google云端的MySQL数据库。只要你懂得使用MySQL就可以完全使用它。但它不能像App Engine Datastore那样自动扩容,因此Google推荐在中小型应用中使用。(ideal for small to medium-sized applications)
  • Google Cloud Storage 
    Google Cloud Storage目前上处于“实验阶段”,因此并不推荐使用。使用它可以向Google云中写入文件、大图片等。但在实际使用过程中,如果真需要写入文件、图片等对象,应该使用Blobstore API而非Google CLoud Storage。未来,Google可能会优化Google Cloud Storage并逐渐替换Blobstore API。当然,这是后话。 
限于篇幅等众多原因,本教程中只讲解App Engine Datastore的使用方式。若你对其他两种方式感兴趣,完全可以参考Google提供的内容自学。其他两种方式操作起来也是非常简便,相关连接已经在上述说明中。

App Engine Datastore

App Engine Datastore是一个强复制数据库(High Replication Datastore)。这意味着,你存入其中的某个数据,会被它复制到不同数据中心的其他机器中以保证同步。App Engine Datastore使用Paxos算法实现数据同步以保证每次查询返回的数据具有一致性。别忘记:你写入存储空间中的数据,可能被存储在Google众多的数据中心中某一个,而下一次你查询时可能又从另外一个数据中心返回数据。
对数据的操作方式来说,App Engine Datastore支持Java Data Objects(JDO)Java Persistence API(JPA)及一种低级别API(Low-level datastore API)。JDO是Apache的标准,JPA是Oracle的标准,如果你使用过的话,应该非常清楚如何使用。JDO、JPA相关的教程,你可以自己查找。本教程中将使用App Engine Datastore原生支持的低级别API读写数据。
和传统的“对象-关系”型数据库相比,App Engine Datastore使用分布式架构以保证能够自动扩展,而且它也不使用“对象-关系”型数据库的方式存储数据。因为和传统数据库比起来,App Engine Datastore具有以下三个明显区别:
  • App Engine Datastore能够根据请求自动扩展
  • 由于App Engine Datastore使用预建索引(pre-build indexs),因此对于索引列类型要求更严格
  • 使用App Engine Datastore时并不需要同一类型的实体(entity)具有相同的属性

Entity(实体)、Property(属性)、Key(键)、Kind(类型)

  • Entity 
    Entity称之为实体,是能够存储到App Engine Datastore的基本单元。在传统数据库中它可以被看作是一条数据。
  • Property 
    Property称之为属性,是每个实体具有的属性,相当于传统数据库中的列或字段。属性有几个非常有意思的特性:
    • 不同类型的实体可以含有相同的属性
    • 同一类型的实体也可以包含不同的属性
    • 同类型的实体相同的属性也可以含有不同类型的值 
    • 由于App Engine Datastore的限制,属性的数据类型有一定的要求,具体内容我们稍后讲解
  • Key 
    Key俗称为键,相当于传统数据库中“主键”。但与传统数据库所不同的是:传统数据库中,往往会选择表中某一列作为逐渐;而在App Engine Datastore中,Key是依附在每个实体身上的特殊对象
  • Kind 
    每一个实体都应属于某种类型,称之为Kind。一般说来,你可以给任何一个实体指定随意的名称作为其类型,但类型名称不能以两个_开头(两个下划线开头的类型是一些特殊类型,这些类型保留给App Engine Datastore使用)
注意:App Engine Datastore对同一类型的实体属性没有做强制要求。因此,同一类型的实体可以含有不同属性,如:某个Person实体可以含有name属性,而另一个Person实体则完全可以没有name属性。表面上看,这样宽松的方式给开发人员带来了巨大方便。但也正因为如此,才有可能出现后续一些列问题(如果你认为那是问题的话)。因此,强烈建议开发人员在自己的应用中对此做出一定的限制

插入数据

以下Java代码将展示如何将一个实体(Entity)存入App Engine Datastore。假设我们需要实现一个类似与StackOverFlow但非常简易的提问回答系统,现在来看看如何将用户提问的内容写入App Engine Datastore中。
    import com.google.appengine.api.datastore.DatastoreService;
    import com.google.appengine.api.datastore.DatastoreServiceFactory;
    import com.google.appengine.api.datastore.Entity
    import java.util.Date;

    Entity queEntity = new Entity("Question");
    queEntity.setProperty("title", "Google App Engine中如何写入数据?");
    queEntity.setProperty("content", "最近在学习GAE相关知识,请问如何将数据写入GAE数据存储中?");
    queEntity.setProperty("createdDate", new Date());
    queEntity.setProperty("keywords", "google app engine,datastore");
    queEntity.setProperty("isClosed", false);

    DatastoreService dataService = DatastoreServiceFactory.getDatastoreService();
    dataService.put(queEntity);
以上代码中可以看出,创建一个实体并将其存入App Engine Datastore是非常简单的过程:
  1. 创建Entity对象
    创建实体对象,只需要实例化com.google.appengine.api.datastore.Entity类即可。 创建Entity对象时指定对象的类型(Kind)可以使用如下构造方法:
    Entity queEntity = new Entity("Question");
    
    创建Entity对象时指定对象的类型(Kind)并且指定该对象的Key可以使用如下构造方法:
    Entity queEntity = new Entity(KeyFactory.createKey("Question", new Date().getTime()));
    
    这种方法创建Entity对象时,不仅指定的创建对象的类型(Kind),同时根据当前时间的毫秒形式创建一个Key对象,从而保证创建对象具有唯一标识。请注意:根据Google提供的API文档可以看出:Entity对象的Key生成方式具有两种:1、在将Entity对象放入App Engine Datastore之后(调用DatastoreService的put方法之后)由系统生成 2、开发人员在创建Entity对象时自行生成。鉴于可能出现的并发问题,还是将创建Key的事情交由App Engine Datastore去实现较好。
  2. 给Entity对象的属性赋值 
    创建Entity对象之后,紧接着就可以为创建的对象设置属性值。给Entity对象设置属性值的过程可以调用public void setProperty(java.lang.String propertyName,java.lang.Object value)方法。该方法传入两个值:第一个值propertyName时该实体即将拥有的属性名,第二个值value是该属性即将拥有的属性值。同样请注意:虽然该方法第二个参数是Object类型,但并不意味着可以随意传入任何不受限制的数据。实际上,App Engine Datastore对存入其中的数据类型有着及其严格的限制。目前,App Engine Datastore支持以下类型的数据: 
     
    尤其注意字符串类型数据的限制:String类型大小不能超过500个Unicode字符,否则会抛出IllegalArgumentException异常。如果你需要存入较大篇幅的文本内容,可以选择com.google.appengine.api.datastore.Text类型,它可以支持高达1M的字符数据,理论上已经足够使用,但在该类型属性上不能建立索引。
  3. 调用DatastoreService将数据写入
    创建实体并给属性赋值之后,使用DatastoreService.put(Entity entity),就可以将其写入App Engine Datastore中。
    //使用工厂获取DatastoreService对象并调用put方法写入数据  
    DatastoreService dataService = DatastoreServiceFactory.getDatastoreService();  
    dataService.put(queEntity);
    
  4. 修改数据

    修改已经存在的Entity对象非常容易,你只需要修改你想要修改的Entity对象的属性,并再次调用DatastoreService.put(Entity entity)方法即可。因为Key不可修改,因此再次调用该方法将会导致后来的数据覆盖之前的数据,从而达到修改数据的目的。
    请注意:App Engine Datastore无法分辨put()方法是企图插入新数据或者修改老数据,它会根据对象的Key进行查找。若找到对象实体对象则覆盖,否则将插入新对象。因此,在修改数据之前,你可以使用事务先查找想要修改的实体对象,再酌情进行处理。

    删除数据

    删除一个Entity对象,只需要调用DatastoreService.delete(Key key)方法即可。该方法传入的参数是你将要删掉的Entity对象的Key。
            DatastoreService dataService = DatastoreServiceFactory.getDatastoreService();
            dataService.delete(queEneity.getKey());
    

    小结

    本章中讲解了以下几个知识点:
    1. Google App Engine提供的三种数据存储方案
    App Engine Datastore: NoSQL数据存储方法(Google推荐使用)
    Google Cloud SQL: Google云上的MySQL数据库(不能扩展,适合中小应用)
    Google Cloud Storage: 仍处于实验阶段的数据存储方法
    2. App Engine Datastore见解及常见概念
    Entity:代表一个实体对象
    Property:代表实体对象的属性
    Key:代表实体对象用以唯一标识的键
    Kind:代表实体对象所属的类型
    3. 使用App Engine Datastore中
    数据插入:使用DatastoreService.put()方法
    数据修改:使用DatastoreService.put()方法
    数据删除:使用DatastoreService.delete()方法

No comments:

Post a Comment