2015-09-06 129 views
0

我有一个使用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属性

+0

定义“检索” 。通过我的意思是你的持久性代码来检索字段,并且你在哪里检查字段值(在那个时候什么是对象状态?)。 –

+0

我还没有与这些工作,但它看起来像我这些集合被定义为“懒惰”,这意味着你需要以某种方式表明你想要的集合填充。另外,如果你实例化这些集合(例如'private Map taskToCommandMap = new HashMap <>();'),它可能会有所作为。 –

+0

Thanks @ Sva.Mu我必须对从查询返回的多个持久对象集合上的#size()方法进行调用才能使其填充 - 但我无法在每个对象的各个字段上调用方法 - 我只是得到一个空指针。 –

回答

1

感谢Neil Stockton的评论,单元测试现在通过了。

取计划在这里记载:http://www.datanucleus.org/products/datanucleus/jdo/fetchgroup.html

的空字段没有加载它们不是由默认值(原语,字符串,日期,对象基元的包装等加载的数据类型中)

为了使上述工作的代码,我移动每个空字段到默认的通过在@Persistance注释指定一个新的属性提取组 - defaultFetchGroup =“真”

@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(defaultFetchGroup="true") 
    private Map<String, String> taskToCommandMap; 

    /** Case 3 - DataSelection is serializable */ 
    @Persistent(defaultFetchGroup="true") 
    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", defaultFetchGroup="true") 
    private Map<String, List<String>> taskToTransitions; 

    // getters and setters omitted