0

示例: s 我有一个与对象 b、c 和 d 相关的 A 类对象 a。
如果我做:

SelectQuery query = new SelectQuery(A.class);
query.addPrefetch("b").setSemantics(PrefetchTreeNode.DISJOINT_PREFETCH_SEMANTICS);
query.addPrefetch("c").setSemantics(PrefetchTreeNode.DISJOINT_PREFETCH_SEMANTICS);
List<?> res = context.performQuery(query);

然后稍后:

SelectQuery query = new SelectQuery(A.class);
query.addPrefetch("d").setSemantics(PrefetchTreeNode.DISJOINT_PREFETCH_SEMANTICS);
List<?> res = context.performQuery(query);

从 a 到 b 和 c 的关系无效(参见 DataRowUtils 第 115 行)。

我使用的是 Cayenne 3.0.2,但在 3.1 和 3.2M1 版本中的行为似乎相同

有没有办法解决这个问题?

我的想法是用这个函数覆盖 A 类中的 CayenneDataObject:

public void writePropertyDirectly(String propName, Object val) {
    if(propName.equals("b") || propName.equals("c")) {
        if(val instanceof Fault && readPropertyDirectly(propName) != null) {
            return;
        }
    }
    super.writePropertyDirectly(propName, val);
}

这是个坏主意吗?它似乎工作。
加载后,我根本不想从数据库中刷新 b 和 c 。
谢谢

4

1 回答 1

0

实际上,这种行为是意料之中的。一对一关系的失效是在 select 上急切地完成的,以保证它们的新视图,并且在需要时应该很容易从内存缓存中恢复它们的前提下。因此,对于一个简单的 FK 关系,当您调用“getB”或“getC”时,您将获得一个故障对象,并且您不会看到数据库查询。

出于几个原因,可能会发生例外情况(读取一对一时的意外查询)。最有可能的是 ObjectContext-local 缓存的急切垃圾收集。为了防止这种情况发生,Cayenne 3.1 和 3.2 提供了将保留策略集指定为“cayenne.server.object_retain_strategy”属性的能力。您可以尝试“硬”策略,看看是否有任何不同。

仅当您知道访问和刷新 A 的所有场景时,您的上述解决方案才可以。通常,它可能会导致难以调试的数据刷新问题。

于 2014-09-30T18:17:43.223 回答