我在使用JDO从Google Cloud Datastore检索对象时遇到问题。令人难以置信的是令人沮丧,因为99.5%的时间我的代码完美运行,但有0.5%的时间缺少某些数据,而且我无法找到复制错误的一致步骤。我相当肯定我的问题在于我是如何设置模型的,或者我是如何查询数据存储区的(我怀疑它可能与延迟加载或默认情况有关)取组,但我不确定。
在我解释发生了什么之前,它将有助于理解模型。
以下是我的模型的简化版本:
@PersistenceCapable
@Inheritance(customStrategy = "complete-table")
public class DataObject {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY, defaultFetchGroup="true")
protected Key theKey;
@Persistent()
protected String name;
//...
}
@PersistenceCapable
public class Class1 extends DataObject{
@Persistent()
@Element(dependent="true")
private List<Class2> listOfClass2 = new ArrayList<Class2>();
//...
}
@PersistenceCapable
public class Class2 extends DataObject{
@Persistent()
@Element(dependent="true")
private List<Class3> listOfClass2 = new ArrayList<Class3>();
//...
}
@PersistenceCapable
public class Class3 extends DataObject{
@Persistent()
private String value;
//...
}
以下是用于查询数据存储的代码:
public class DataManager {
public DataObject get(
User user,
Class type,
Long id) throws OAuthRequestException
{
PersistenceManager mgr = getPersistenceManager();
DataObject obj = null;
try
{
obj = mgr.getObjectById(type, id);
getAllChildren(obj);
}
finally
{
mgr.close();
}
if(obj != null)
{
return obj;
}
else
{
throw new EntityNotFoundException("Entity not found");
}
}
/**
* Returns all of the children of the given object
* and their children etc. It is intended to 'touch' every object
* in the tree to accommodate for lazy loading.
*/
private List<StoredDataObject> getAllChildren(DataObject obj)
{
//...
}
}
问题是,偶尔会出现查询,其中包含所有&#39;名称&#39;给定级别的字段为空。例如,如果我检索Class1的对象,则所有子Class2对象都将具有&#39; name&#39;属性等于&#34;&#34;。数据肯定在数据存储中,因为如果我再次运行查询,它们将被正确填充。我从未见过任何其他属性为空,只有名称字段。有时它出现在Class2级别,有时是Class3,但从不出现Class1(据我所见)。
我的理解是,任何String属性都应该自动包含在默认的fetch组中,但是我可能错过了一个强制名称&#39;每次要检索的属性?
新观察:当发生这种情况时,只要我使用相同的用户凭据运行相同的查询,就会持续发生大约15分钟。这可能与缓存有关吗?
答案 0 :(得分:-2)
我遇到了一个非常类似的问题。如果这是一个答案,因为我知道我肯定会说,“只需在返回对象之前询问你的记录器值。”
我有一个Swift iOS应用程序连接到我在GAE中运行的java servlet,其中JDO持久性存储到数据存储中(使用GAE插件在Eclipse Kepler中构建和部署)。
由于在生成端点rpc文件时遇到错误,我已根据本网站上的一些帖子对最新的Eclipse GAE插件进行了回归,但其他方面都是默认配置。
我遇到的问题是我有一个表示外键的字段(location.playerId ...虽然没有强制执行此约束,但在任何情况下都不应该引起问题)。我在Swift应用程序中有日志输出,提供以下内容(注意:输出来自INSERT和UPDATE方法调用端点之前,其中“PROXIMAL”行在返回时测试响应对象属性值。返回的位置POJO是处理了响应中的两个案例。):
$$$$$$$$ INSERT LOCATION playerId:6657911736500224
$$$$$$$$ PROXIMAL playerId:nil
$$$$$$$$更新位置playerId:6657911736500224
$$$$$$$$ PROXIMAL playerId:nil
注意传入的playerId值在响应中返回为nil?! INSERT和UPDATE方法是Eclipse生成的默认代码(请参阅下面的PlayerEndpoint的更新列表)。如果我在java servlet中添加一个记录器并输出location.getPlayerId()方法的值,那么我在Swift应用程序中得到如下输出:
$$$$$$$$ INSERT LOCATION playerId:6657911736500224
$$$$$$$$ PROXIMAL playerId:6657911736500224
$$$$$$$$更新位置playerId:6657911736500224
$$$$$$$$ PROXIMAL playerId:6657911736500224
怎么样?!只需通过查询servlet方法中的描述符方法(并且不更改端点代码正在执行的操作),并填充值并通过端点调用返回。这种行为似乎符合可能被解释为某种“延迟加载”的行为,在明确的交互之前不会被解雇。
以上示例使用位置POJO上的playerId字段/方法进行。但是我在Player POJO上有相同的行为,但是使用了player.getDeviceToken()方法。下面是Eclipse中生成的默认代码,作为Player POJO的端点,包含记录器输出。
`
public Player updatePlayer(Player player) {
PersistenceManager mgr = getPersistenceManager();
try {
if (!containsPlayer(player)) {
throw new EntityNotFoundException("Object does not exist");
}
player.setUpdated(new Date());
log.info("(updatePlayer) " + player.getDeviceToken());
mgr.makePersistent(player);
log.info("(updatePlayer post persist) " + player.getDeviceToken());
} finally {
mgr.close();
}
log.info("(updatePlayer prereturn) " + player.getDeviceToken());
return player;
}
`
(*如果这有助于使Tom的问题可重复并且原因相同):除了将一些值写入记录器之外,任何天才会遇到这个并解决它?!