在前面几节中我们了解了cube的创建和query的创建。有了这2样东西后,我们就可以开始执行mdx语句了。在第二小节中,我们了解了mdx的执行顺序。
- 先执行from,即表示从哪个cube中获取结果。
- 再执行where,with和axis,即获取member阶段。
- 有了所有依赖的成员后,最后执行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成员属性。成员读取过程:
- smartMemberReader.getMemberChildren(parentMembers,children,constrain);
- 最终通过source.getMemberChildren()…,其中反过来会把找到的children赋予mapKeyToMember。
- 最终除了将结果返回在children输出参数中,同时也对mapMemberToChildren赋值了。