【问题标题】:How to get a properly typed List from a ReflectionDBObject如何从 ReflectionDBObject 中获取正确类型的列表
【发布时间】:2011-03-18 18:07:21
【问题描述】:

我有一个类似的模型类

public class MyClass extends ReflectionDBObject {
    private List<NiceAttribute> attributes;    
    ...
}

public class NiceAttribute extends ReflectionDBObject {
    ...
}

我以类型安全的方式创建它,例如

List<NiceAttribute> attrs = new ArrayList<NiceAttribute>();
attrs.add(new NiceAttribute());
MyClass myClass = new MyClass();
myClass.setAttributes(attrs);

然后将其保存到 mongo,并使用类似的代码检索

DBCollection col = ...;
col.setObjectClass(MyClass.class)
MyClass foundObject = (MyClass)col.findOne();

但问题是foundObjectattributes 变成了BasicDBObject 的列表。看起来驱动程序无法(或不想)检测列表项类型。这是驱动程序限制,还是我错过了什么?什么是解决该问题的优雅解决方法?

顺便说一句,我知道 Morphia 等。也许它可以解决问题。但是我的项目很小,我不想让事情复杂化,增加一层抽象。

【问题讨论】:

    标签: java mongodb


    【解决方案1】:

    您应该使用 Morphia。它增加了对 POJO 和嵌入式对象(和集合)的支持。它没有驱动程序要求您的类看起来像Map&lt;String, Object&gt; 的任何限制。

    【讨论】:

    • Morphia 比驱动程序慢大约 10-15 倍。您最好编写自己的代码来进行映射。
    • 我们在 morphia 中进行了性能测试,结果表明这不是真的。如果您有一些测试显示此性能问题,如果您可以分享它们会很好。
    • 我实际上已经完成了非常基本的测试,我编写了大约 10-20k 次相同的条目,使用驱动程序,然后是 Spring Mongo Db,然后是 Morphia。 Driver 是最快的,Spring Mongo 慢了大约 2 倍,morphia 大约慢了 7-10 倍。即使在具有真正集合分片(在多台机器上)的 mongo 上,它仍然较慢。您可以轻松地对此进行测试。
    • 正如我所说,morphia 中的单元测试没有显示这一点。你能提供你正在使用的测试吗?
    • 嗯,Morphia 的测试结果表明 Moprphia 最快这一事实可能有点偏颇。尝试保存类似 100k 元素的东西,每个元素都有 2 个数字属性,一个字符串一个(应该像 10-20k 字符串),也许还有一个包含 10-20 个元素的类似实体的嵌入式数组。
    【解决方案2】:

    嗯,有一个解决方案,但你不会喜欢它。基本上,您可以为对象中的内部路径指定相应的类。这是我所做的,并且有效:

    public class Release extends ReflectionDBObject {
    
        //other fields omitted    
    
        private List<ReleaseDetailsByTerritory> releaseDetailsByTerritory = new ArrayList<ReleaseDetailsByTerritory>();
    
    }
    
    public class ReleaseDetailsByTerritory extends ReflectionDBObject { //...}
    

    现在,如果我只是这样做:

        releaseColl.setObjectClass(Release.class);
        releaseColl.setInternalClass("ReleaseDetailsByTerritory.0", ReleaseDetailsByTerritory.class);
        Release r = (Release) releaseColl.findOne();
        //the internal list will contain ReleaseDetailsByTerritory type objects (not DBObjects)
        System.out.println(r.getReleaseDetailsByTerritory().get(0).getClass().getName());
    

    这里的糟糕之处在于您不能(或者至少我还没有找到如何)为嵌入式数组的所有元素指定映射类。你不能这样做:

    releaseColl.setInternalClass("ReleaseDetailsByTerritory", ReleaseDetailsByTerritory.class);
    

    releaseColl.setInternalClass("ReleaseDetailsByTerritory.*", ReleaseDetailsByTerritory.class);
    

    您必须指定嵌入数组的任何可能元素的映射类:

    releaseColl.setInternalClass("ReleaseDetailsByTerritory.0", ReleaseDetailsByTerritory.class);
    releaseColl.setInternalClass("ReleaseDetailsByTerritory.1", ReleaseDetailsByTerritory.class);
    releaseColl.setInternalClass("ReleaseDetailsByTerritory.2", ReleaseDetailsByTerritory.class);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-30
      • 2018-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-26
      • 1970-01-01
      • 2012-02-21
      相关资源
      最近更新 更多