我有一个使用JDO的Google App Engine项目,当我检索包含集合集合的类时,每个集合都为null,而类中的简单字段被检索为OK。为什么将集合检索为空?
我正在工作的基础上我使用了错误的注释,所以增强器在运行时礼貌地忽略这些字段 - 但看不到它在哪里。
当我通过调试时,我可以看到我的调用makePersistent更新对这些字段的引用,它们仍然非空并且填充。当我使用持久化对象中的ID再次检索它时,这些字段为空。
我的持久对象子类是一个通用持久对象,如下所示。
@PersistenceCapable
@Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
public abstract class PersistentObject {
@PrimaryKey
@Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
protected Long id;
// getters and setters omitted
}
我试图存储和检索的子类看起来像这样。名称字段(情况1)检索OK,但taskToCommandMap,taskToDefaultCommandParams和taskToTransitions全部返回为空。
由于DataNucleus对此question的评论,我试图将collection的集合标记为serializable =“true”。
@PersistenceCapable
public class ConcretePersistentObject extends PersistentObject {
/** Case 1 - Stored and retrieved fine */
@Persistent
private String name;
/** Case 2 - A new object ref is visible in the debugger for this after the call to makePersistent , but when retrieved it's null */
@Persistent
private Map<String, String> taskToCommandMap;
/** Case 3 - DataSelection is serializable */
@Persistent
private Map<String, Map<String, DataSelection>> taskToDefaultCommandParams;
/** Case 4 - Serialized because GAE doesn't support persisting Map values of type LinkedList or ArrayList.
*/
@Persistent(serialized="true")
private Map<String, List<String>> taskToTransitions;
// getters and setters omitted
DataSelection中引用了一个接口,它扩展了Serializable。没有任何实现DataSelection的类在注释中被引用,它们都不是@PersistenceCapable。
public interface DataSelection extends Serializable {...}
编辑1:实际的检索发生在一个通用的DAO,
public T get(Long id) {
if(id == null) {
return null;
}
PersistenceManager pm = pmf.getPersistenceManager();
T persistentObject = null;
try {
persistentObject = (T) pm.getObjectById(persistentClass, id);
} catch (Exception e) {
logger.warning(e.toString());
e.printStackTrace();
return null;
} finally {
pm.close();
}
return persistentObject;
}
我生成并存储一个实例,然后调用get方法,然后通过一个测试领域之一:
ConcretePersistentObject cpo1 = buildAndStore();
ConcretePersistentObject cpo2 = concretePersistentObjectDao.get(cpo1.getId());
assertEquals(cpo1.getName(), cpo2.getName(); // passes
assertEquals(true, cpo1.getTaskToCommandMap().keySet().equals(cpo2.getTaskToCommandMap().keySet())); // null pointer exception
在这一点上,cpo1填充了原始数据。它有一个带有数据的HashMap的引用。 cpo2是一个对象,它具有简单的字段设置,但地图现在是空值。
为什么我看到空值返回这些字段?我应该做什么不同? ...朗姆酒在哪里?
编辑2: 两个对象在比较时处于TRANSIENT状态。
我没有设置任何地方detachAllOnClose,的System.out.println(pmfInstance.getProperties())不显示它设置,并且DataNucleus将DOCO表明,它默认为false。调用pm.getObjectById前
权FetchPlan看起来是这样的:
FetchPlan.DetachmentOptions = 1
FetchPlan.MaxFetchDepth = 1
FetchPlan.FetchSize = 0
datanucleus.retainValues =在真PMF属性
定义“检索” 。通过我的意思是你的持久性代码来检索字段,并且你在哪里检查字段值(在那个时候什么是对象状态?)。 –
我还没有与这些工作,但它看起来像我这些集合被定义为“懒惰”,这意味着你需要以某种方式表明你想要的集合填充。另外,如果你实例化这些集合(例如'private Map taskToCommandMap = new HashMap <>();'),它可能会有所作为。 –
Thanks @ Sva.Mu我必须对从查询返回的多个持久对象集合上的#size()方法进行调用才能使其填充 - 但我无法在每个对象的各个字段上调用方法 - 我只是得到一个空指针。 –