mondrian 源码解读(七)-读取member

在前面几节中我们了解了cube的创建和query的创建。有了这2样东西后,我们就可以开始执行mdx语句了。在第二小节中,我们了解了mdx的执行顺序。

  1. 先执行from,即表示从哪个cube中获取结果。
  2. 再执行where,with和axis,即获取member阶段。
  3. 有了所有依赖的成员后,最后执行Cell的值。

cube的创建已经在前一节中讲过了,接着是member获取阶段,由于这一阶段分为3部分,内容比较多。所以下面我们先将member是如何读取的,后几节再介绍它的执行过程。

MemberSource

所有对成员的读取操作都是通过MemberSource来完成的。
MemberSource基本功能就是是读取层次的成员操作。
我们看下它的基本接口:

public interface MemberSource {

    RolapHierarchy getHierarchy();

    boolean setCache(MemberCache cache);

    List<RolapMember> getMembers();

    List<RolapMember> getRootMembers();

    void getMemberChildren(
        RolapMember parentMember,
        List<RolapMember> children);

    void getMemberChildren(
        List<RolapMember> parentMembers,
        List<RolapMember> children);

    int getMemberCount();

    RolapMember lookupMember(
        List<Id.Segment> uniqueNameParts,
        boolean failIfNotFound);
}    

从上面我们可以看到,有3个最基本的接口,分别是获取层次,即当前的MemberSource属于哪个层次,设置缓存对象(为了从缓存中读取member),和获得当前层次的成员。这就是MemberSource的核心功能。

MemberReader

我们先看MemberReader的层次图。

从上图中我们看到,MemberReader是继承的MemberSource,所以MemberReader具有MemberSource所有的功能。那么它有哪些功能呢?
我们看看它的接口:

interface MemberReader extends MemberSource {

    RolapMember getLeadMember(RolapMember member, int n);


    List<RolapMember> getMembersInLevel(
        RolapLevel level);


    void getMemberRange(
        RolapLevel level,
        RolapMember startMember,
        RolapMember endMember,
        List<RolapMember> list);

    int compare(
        RolapMember m1,
        RolapMember m2,
        boolean siblingsAreEqual);

    Map<? extends Member, Access> getMemberChildren(
        RolapMember member,
        List<RolapMember> children,
        MemberChildrenConstraint constraint);

    Map<? extends Member, Access> getMemberChildren(
        List<RolapMember> parentMembers,
        List<RolapMember> children,
        MemberChildrenConstraint constraint);

    List<RolapMember> getMembersInLevel(
        RolapLevel level,
        TupleConstraint constraint);

    int getLevelMemberCount(RolapLevel level);

    MemberBuilder getMemberBuilder();

    RolapMember getDefaultMember();

    RolapMember getMemberParent(RolapMember member);

    RolapMember substitute(RolapMember member);

    RolapMember desubstitute(RolapMember member);

    RolapMember getMemberByKey(
        RolapLevel level,
        List<Comparable> keyValues);
}

从上面大家发现没,MemberReader更细化功能,它可以获取到Level上的成员,也可以获取成员的父成员或者成员的子成员,并且在获取成员的时候可以添加约束条件。有了这些功能,我们就可以任意的获取成员了,所以MemberReader是成员获取的主接口。

具体实现

SmartMemberReader

SmartMemberReader实现了MemberReader接口,它实现了维度成员及其子成员的缓存,如果有一个成员位于缓存中,则还会有一个其子成员的列表。它同时缓存了level下的成员们。该类主要的成员有:

  • source:MemberReader,用于实际从数据库中读取维度成员值。
  • mapMemberToChildren:map,实现成员及其子成员的映射, key为RolapMember,value为List
  • mapKeyToMember: map ,实现所有成员的缓存,其中的key为MmberKey
  • mapLevelToMembers: map,实现级别及其所有成员的映射, key为RolapLevel,value为List

SqlMemberSource

SqlMemberSource是最终更数据库打交道的类,它会针对要查询对Level生成一个sql,该sql最终通过数据库执行,将查询结果返回后拼装成member。需要注意的一点是,如果该member有parentmember,必须要生成其对应的parentmember。生成过程即先递归的在level中查找其上一级level的member是否缓存,如果没有缓存,则将其加入查询列表中,直到上一级为空或缓存了member。找到所有要查询的level后,最后一次性生成sql向数据库查询数据。

SmartMemberReader的source其实为mondrian.rolap.SqlMemberSource类,该类中反过来又存储了SmartMemberReader对象,作为其cache成员属性。成员读取过程:

  1. smartMemberReader.getMemberChildren(parentMembers,children,constrain);
  2. 最终通过source.getMemberChildren()…,其中反过来会把找到的children赋予mapKeyToMember。
  3. 最终除了将结果返回在children输出参数中,同时也对mapMemberToChildren赋值了。