我正在使用Google App Engine对系统进行编码,我只需将对象放入数据存储区即可。我可以使用datastore.put()
方法,但我需要知道该对象是否已存在以计算我拥有的新对象的数量。
据我所知,我有以下选项(假设我将密钥作为属性和实体密钥):
private Entity getEntity(String key)
{
DatastoreService datastore =
DatastoreServiceFactory.getDatastoreService();
// Build a query to select this entity from the database:
Query q = new Query("MyEntity");
q.setKeysOnly();
// Add a filter for the key attribute:
q.addFilter("key", Query.FilterOperator.EQUAL, key);
PreparedQuery pq = datastore.prepare(q);
// Select a single entity from the database
// (there should be no more than one matching row anyway):
List<Entity> list = pq.asList(FetchOptions.Builder.withLimit(1));
if (!list.isEmpty())
// Return the found entity:
return list.get(0);
else
return null;
}
或
private Entity getEntity(String key)
{
DatastoreService datastore =
DatastoreServiceFactory.getDatastoreService();
// Get a key that matches this entity:
Key key = KeyFactory.createKey("MyEntity", key);
try {
return datastore.get(key);
} catch (EntityNotFoundException e) {
// Entity does not exist in DB:
return null;
}
}
我倾向于使用第二个,因为它似乎更直接,但我担心它可能不会以这种方式使用,因为它会引发异常,并且可能会产生开销。
哪种方法更适合检查数据库中是否存在实体?
有更好的方法吗?
答案 0 :(得分:3)
除非您的实体很大并且具有许多属性,否则执行get会更快 - 在这种情况下,仅键查询可能会更快。如果性能在这里可能是一个重要的问题,我会建议基准测试 - 但如果没有,后一种方法更直接。
答案 1 :(得分:1)
如果Entity
需要唯一性,如果有多个线程在完全同时访问数据库,那么即使这种检查也不能保证唯一性。
在这种情况下,两个线程都不会看到任何存在,并同时创建新对象。即使是交易也无法防止这种情况发生,因为应用程序不会阻止read
之间的访问以确定唯一性,write
来保存实体。
我知道这听起来不太可能,但这肯定发生在我们身上,例如当我们运行MapReduce作业以批量更新/创建超过8个分片的大批记录(100k +)时。
保证对象唯一的唯一方法是指定其Key的name
属性。这将使数据存储create
成为新实体(如果不存在),否则它将update
实体存储到最后保存的对象。
所以而不是:
Entity entity = new Entity("MyKind");
这确保每个属性只有一个唯一的实体:
String myPropertyValue = getPropValue();
Entity entity = new Entity("MyKind", myPropertyValue);
ds.put(entity); // Ensures only one Entity per this property value