The datastore is designed with web applications in mind, with an emphasis on read and query performance.
要知道,datastore是为Web应用程序而设计的,其重点关注的是读取和查询的性能。
All queries are pre-indexed for fast results over very large data sets.
为了在大量数据集中快速查询到结果,在datastore中所做的所有查询都必须事先建立索引。与在关系型数据库系统中建立索引的方式不同,在Google App Engine for Java应用中,整个应用程序所使用到的索引被保存在一个XML文件中。你可以手工编写,也可以由Google Plugin for Eclipse自动生成。
With the App Engine datastore, every attempt to create, update or delete an entity happens in a transaction .
对App Engine datastore而言,每次创建、更新或删除一个实体的行为都在一个事务中完成。
All entities fetched, created, updated or deleted in a transaction must be in the same entity group.
在一个事务中,对多个实体进行增、删、改、查操作时,这些实体必须属于同一“实体组”。在这里,对“实体组”的概念不好理解,下面以一组代码段来解释:
public class Employee { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Long id; @Persistent private String firstName; @Persistent private String lastName; @Persistent private Date hireDate; ... }
public class ContactInfo { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent private String streetAddress; @Persistent private String city; @Persistent private String stateOrProvince; @Persistent private String zipCode; ... }
Employee em = new Employee("Jiankang", "Jin", new Date()); ContactInfo info = new ContactInfo("ZhiChun Road", "Beijing", "Beijing", "010"); PersistenceManager pm = PMF.get().getPersistenceManager(); Transaction tx = pm.currentTransaction(); try { tx.begin(); pm.makePersistent(em); pm.makePersistent(info); tx.commit(); } catch (Exception e) { System.out.println(e); } finally { if (tx.isActive()) { tx.rollback(); } pm.close(); }
运行Servlet,在控制台看到:
javax.jdo.JDOFatalUserException: Illegal argument NestedThrowables: java.lang.IllegalArgumentException: can't operate on multiple entity groups in a single transaction.
修改后:
public class Employee { ... @Persistent private ContactInfo contactInfo; ... }
ContactInfo info = new ContactInfo("ZhiChun Road", "Beijing", "Beijing", "010"); Employee em = new Employee("Jiankang", "Jin", new Date(), info); PersistenceManager pm = PMF.get().getPersistenceManager(); Transaction tx = pm.currentTransaction(); try { tx.begin(); pm.makePersistent(em); pm.makePersistent(info); tx.commit(); } catch (Exception e) { System.out.println(e); } finally { if (tx.isActive()) { tx.rollback(); } pm.close(); }
再次运行Servlet,无异常。查看http://127.0.0.1:8080/_ah/admin,Kind Employee有一条记录,Kind ContactInfo有一条记录(注意:不是两条,代码pm.makePersistent(info)是不必要的,即使写了,也只保存一条ContactInfo记录)。而且,The key of the ContactInfo
entity has the key of the Employee
entity as its entity group parent. 这句话可能引起歧义,我原以为前者的key包含后者的key,但结果是:
the key of Employee is 'agByDgsSCEVtcGxveWVlGAEM',
and the key of ContactInfo is 'agByHwsSCEVtcGxveWVlGAEMCxILQ29udGFjdEluZm8YAgw'.
在Google Groups上请教了该问题,上述现象是正常的,两者的key确实不是简单的字符串包含关系。但可以肯定的是:
KeyFactory.stringToKey(employeeKeyString).equals(KeyFactory.stringToKey(con
tactInfoKeyString).getParent())
参见:http://groups.google.com/group/google-appengine-java/browse_thread/thread/76ca595de10a5a5a/95509d1364acc9d4?lnk=gst&q=jinjiankang1980#95509d1364acc9d4
Entity groups are defined by a hierarchy of relationships between entities.
如果多个实体间有关联关系,则它们组成一个实体组。据我我理解,这里的“a hierarchy of relationships”就是指UML中的组合或聚合。
(如何使用附件源代码注:使用Google Eclipse插件建立工程,工程名GAE_Test,包名com.gaetest)
(所使用的GAE JDK:appengine-java-sdk-1.2.2)