精华内容
下载资源
问答
  • Mondrian

    千次阅读 2012-08-28 17:41:32
    Mondrian是一个开源项目。一个用Java写成的OLAP(在线分析性处理)引擎。它用MDX语言实现查询,从关系数据库(RDBMS)中读取数据。然后经过Java API用多维的方式对结果进行展示。我们都知道,在线分析处理(OLAP)要实时...

    Mondrian是一个开源项目。一个用Java写成的OLAP(在线分析性处理)引擎。它用MDX语言实现查询,从关系数据库(RDBMS)中读取数据。然后经过Java API用多维的方式对结果进行展示。
    我们都知道,在线分析处理(OLAP)要实时地分析大量数据。“online”这个词的含义就是即使相关的数据量是巨大的——可能以GB为单位——系统也要足够快的响应以显示结果。
    OLAP用了多维分析的技术。尽管关系型数据库所存储的所有数据都是以行和列的形式存在的,但一个多维数据集还是可以由轴(axes)和单元(cell)组成。
     
    在上面的例子中,时间是个维度(dimension),而它下面的层次(Hierarchies)又分为半年、季度等级别(Level)。
    二、感性认识——运行一个小实例

    我们暂时先不讨论Mondrian所用到的一些技术。我们可以先从一个小例子开始,不必在意每个细节,只是希望大家有个感性认识先。在实施这个例子的过程中,或许读者就能见些端倪。
    首先应该到http://sourceforge.net/projects/mondrian/下载mondrian的最新版本。这是一个zip包,包括我们要用到的lib和一个例子。
    当然,读者完全可以运行mondrian自带的实例,不过这个例子有些纷繁复杂,除了Mondrian本身还有其它技术在里面,不大容易讲清楚,也不太适合初学者学习。所以,笔者在这里设计一个简洁干净的最小化实例。
    本文所阐述的实例环境是Windows2000+Tomcat+Oracle。并且认为读者已经针对jdk和Tomcat做了正确的开发环境的设置。
    2.1准备工作

    将pentaho/mondrian/lib下的mondrian.war解压后放到%Tomcat%/webapp/下面

    2.2数据库结构

    在这个tiny的系统中,数据库有3个表tb_employee(职员表),tb_time(时间表),tb_salary(薪酬表)。表结构如下:
    drop table tb_employee;
    create table tb_employee
    (
         employee_id     number,             --职员id    
         employee_name   varchar2(10)        --职员姓名
    );
     

    drop table tb_time;
    create table tb_time
    (
        time_id   number,        --时间id
        the_year  char(4),       --年
        the_month char(2)        --月
    );
     

    drop table tb_salary;
    create  table tb_salary
    (
        employee_id  number,                --职员id   
        time_id      number,                --时间id
        salary       number(19,4)           --薪酬
    );
     

    当然,为了使系统能够运行,还需要读者向数据库表中插入一些数据。

    insert into tb_employee(employee_id,employee_name)values(001,'娅娅');
    insert into tb_time(time_id,the_year,the_month)values(1,'2011','05');
    insert into tb_salary(employee_id,time_id,salary)values(001,'1','5000');

    insert into tb_employee(employee_id,employee_name)values(002,'梅梅');
    insert into tb_time(time_id,the_year,the_month)values(2,'2011','04');
    insert into tb_salary(employee_id,time_id,salary)values(002,'2','10000');

    insert into tb_employee(employee_id,employee_name)values(002,'芳芳');
    insert into tb_time(time_id,the_year,the_month)values(3,'2011','04');
    insert into tb_salary(employee_id,time_id,salary)values(003,'3','10000');
    2.3根据数据库表的结构,书写schema文件

    <?xml version="1.0"?>
    <Schema name="Mondrian">
    <Cube name="CubeTest">
        <Table name="TB_SALARY" />
       
        <Dimension name="Employee"  foreignKey="EMPLOYEE_ID" >
            <Hierarchy hasAll="true" primaryKey="EMPLOYEE_ID">         
                <Table name="TB_EMPLOYEE" />
            <Level name="employeeId" column="EMPLOYEE_ID"   uniqueMembers="true" >
                    <Property name="employeeName" column="EMPLOYEE_NAME"/>
                </Level>
            </Hierarchy>
        </Dimension>
        <Dimension name="Time" foreignKey="TIME_ID" >
            <Hierarchy  hasAll="false" primaryKey="TIME_ID" >
                <Table name="TB_TIME" />
                <Level name="year" column="THE_YEAR" uniqueMembers="false" />
                <Level name="month" column="THE_MONTH" uniqueMembers="false" />
            </Hierarchy>
        </Dimension>       
       
        <Measure name="Salary" column="SALARY" aggregator="sum" />
        </Cube>
    </Schema>
     

    文件路径为mywebapp/WEB-INF/test.xml
    2.4利用MDX查询   mywebapp/test.jsp
    <%@ page import="mondrian.olap.*"%>
    <%@ page import="java.io.PrintWriter" %>
    <%
     Connection connection = DriverManager.getConnection("Provider=mondrian;Jdbc=jdbc:oracle:thin:hibuser/password@localhost:1521:orcl;  Catalog=file:///F:/pentaho/biserver-ce/tomcat/webapps/mondrian/WEB-INF/queries/test1.xml; JdbcDrivers=oracle.jdbc.driver.OracleDriver;",null);    
     String queryStr="select {[Measures].[Salary]} ON COLUMNS,{[Employee].[employeeId].Members} ON ROWS from CubeTest ";
     
     Query query =connection.parseQuery(queryStr);
     Result result = connection.execute(query);
    PrintWriter pw = new PrintWriter(System.out);
    result.print(pw);
    pw.flush();
    System.out.println("successful!");
    %>

     

    2.5运行

    这时启动tomcat,在浏览器地址栏中输入
    http://localhost:8080/mondrian/test.jsp即可。
    三、深入探讨

    3.1 API

    mondrian为客户端应用程序提供了API接口以进行查询。 而这些API对于任何用过JDBC的人都会觉得似曾相识的。主要的不同点是查询语言的不同:Mondrian用的是MDX('Multi-Dimensional eXpressions'),而JDBC则用的是SQL。

    和JDBC一样,也是要经过建立连接,形成查询语句,执行查询得到结果集等几个步骤的。

    我们来看看mondriantest.jsp的代码
    第1行:import mondrian.olap.*
    这是引入我们所需的类,下面要用到的DriverManager、Connection、Query、Result都在这个package内。这个package一般位于mondrian.jar中。
    第2行:Connection connection =
      DriverManager.getConnection
    ("Provider=mondrian;                
     Jdbc=jdbc:oracle:thin:@xxx.xxx.xxx.xxx:1521:dbname;
    JdbcUser=dbuser;                                    
     JdbcPassword=dbpasswd;                               
    Catalog=file:///c:/Tomcat4.1/webapps/mywebapp/WEB-INF/mondriantest.xml;
    JdbcDrivers=oracle.jdbc.driver.OracleDriver;",null,false); 
    通过DriverManager创建一个Connection的实例,建立起数据库连接。
    其中Jdbc=jdbc:oracle:thin:@xxx.xxx.xxx.xxx:1521:dbname; 是设置数据库的ip和库名。JdbcUser=dbuser;  设置数据库用户。JdbcPassword=dbpasswd;   设置用户密码。而
    Catalog=file:///c:/Tomcat4.1/webapps/mywebapp/WEB-INF/mondriantest.xml; 就是设置MDX语句查询要对应的schema文件的路径
    第3行:String queryStr=
    "select {[Measures].[Salary]} ON COLUMNS,
    {[Employee].[employeeId].Members} ON ROWS
    from CubeTest ";
    形成MDX的查询语句。MDX语句的形式和schema文件的设定是密切相关的,当然schema文件的形成也是由数据库结构决定的。
    第4行:Query query =connection.parseQuery(queryStr);对MDX语句进行分析处理,是否符合schema文件定义、数据库结构和数据库数据。
    第5行:Result result = connection.execute(query);执行查询,得到结果集。
    我们发现Query类似于JDBC的Statement,而Result则酷似于ResultSet。
    3.2 schema

    3.2.1什么是schema

    schema定义了一个多维数据库。包含了一个逻辑模型,而这个逻辑模型的目的是为了书写MDX语言的查询语句。这个逻辑模型实际上提供了这几个概念:Cubes,维度(Dimensions), 层次(Hierarchies),级别(Levels),和成员(Members)。

    而schema文件就是编辑这个schema的一个xml文件。在这个文件中形成逻辑模型和数据库物理模型的对应。

    3.2.2 schema的逻辑结构

    3.2.2.1 Cube

    一个Cube是一系列维度(Dimension)和度量(Measure)的集合区域。在Cube中,Dimension和Measure的共同地方就是共用一个事实表。

    例:

    <Cube name="CubeTest">
        <Table name="TB_SALARY" />
       …….

    </Cube>

    <Table>标签确定了所用的事实表的表名。

    3.2.2.2 Measure

    一个度量,简单的说,就是要被计算的值。

    例:

    <Measure name="Salary" column="SALARY" aggregator="sum" />

    <Measure>标签有3个必要的属性name(度量名),column(在事实表中的字段名), aggregation(聚合所用的方法)。

    3.2.2.3 Dimenesion

    而维度一般有其相对应的维度表。

    例:

    <Dimension name="Time" foreignKey="TIME_ID" >
            <Hierarchy  hasAll="false" primaryKey="TIME_ID" >
                <Table name="TB_TIME" />
                <Level name="year" column="THE_YEAR" uniqueMembers="false" />
                <Level name="month" column="THE_MONTH" uniqueMembers="false" />
            </Hierarchy>
    </Dimension>
    一般Dimesion包含层次(Hierarchy),而hierarchy是由级别(Level)组成。
    <Dimension>标签的foreignKey是事实表中的字段,<Hierarchy>标签的primaryKey是维度表中的字段,通过这种方式把事实表和维度表关联起来。<Hierarchy>标签下的<Table>标签就指明了维度表名。而若干个Level对应着维度表的若干字段。
    3.3 MDX语言

    MDX是为了查询多维数据的,而SQL是为了查询关系数据库的。而Mondrian所涉及到的一些MDX概念、MDX语法以及系统定义的MDX函数和微软的MDX十分接近,差别微小。完全可以参考微软的帮助文档进行学习。在此就不在赘述。
    四、结语

    Mondrian作为基于java的OLAP引擎,而且是开源的项目,为那些基于java的项目而要脱离微软构架但又不得不对大量数据进行分析的项目又提供了一种可行的方案。希望它也能象蒙得里安·皮特对抽象艺术的发展产生影响一样起到一定的作用。


    展开全文
  • mondrian

    2015-07-07 17:28:00
    成员 dimension 的 member是某个level的具体值 模型 物理模型 fact table , dimension table , aggregate table 逻辑模型 cube, measure, dimension ...1.1 []用于dimension name,level name,member ...

    成员

    1. dimension 的 member是某个level的具体值

    模型

    1. 物理模型

      fact table , dimension table , aggregate table

    2. 逻辑模型

      cube, measure, dimension

    071727160339639.png

    MDX

    1. mdx和sql的区别
      1.1 []用于dimension name,level name,member
      1.2 where指定切片,对没有在轴上出现的dimension进行限定
      1.3 没有group by,隐形的进行分组(?)
      1.4 没有order by,有排序函数,针对某个轴

    轴 axis

    1. 别名

      axis(0)....axis(4) 对应的别名为columns,rows,pages,chapters,sections

      使用别名不能跳过

    2. 轴和维度

      如果多余两个轴,没有办法在平面上表示.

      如果一个轴多余一个维度,需要把多个维度交叉(crossjoin or *)后放到轴上.

    切片维度

    1. 切片维度和轴维度(hive中也有切片的概念)

      切片维度是出现在where语句中的维度,轴维度是出现在select中的维度

      一个维度不能既是轴维度上,又是切片维度.

      ###### 1.1 默认成员

      如果一个维度既不是轴维度,又不是切片维度,就会用该维度的默认成员进行切片.

      一般维度的默认成员是[All ****],因为默认对这个维度的所有成员数据进行聚集操作.

      函数defaultMember返回维度的默认成员.

      如果没有All成员,默认成员就是第一个成员.

    2. 切片维度 认为是对cude从某个方向进行切片得到了一个子立方体.

    元组和集合

    1. 元组和集合是mdx的两种数据类型,也是mdx语句的构件

      ###### 2. 元组

      元组是一个或多个dimension的member的组合.单个member可以认为是一个简单的元组.当一个元组有多个维度时,一个维度只能有一个成员,也就是只能出现一次.

      有多个维度的元组,必须用小括号括起来.例如:([Customer].[Chicago, IL], [Time].[Jan, 2005])

    函数

    1. defaultMember

      返回维度的默认成员:[Product]. defaultMember

    转载于:https://www.cnblogs.com/next-ten-years-2023/p/4627662.html

    展开全文
  • mondrian3.5

    2018-09-13 16:40:21
    Mondrian是一个开放源代码的Rolap服务器,使用java开发的。它实现了xmla和jolap规范,而且自定义了一种使用mdx语言的客户端接口。Mondrian是olap服务器,而不是数据仓库服务器,因此Mondrian的元数据主要包括olap...
  • Mondrian in Action

    2019-05-09 16:03:10
    Mondrian in Action
  • 概述 该存储库包含一个基于的REST API,用于通过查询关系数据源。 目录 动机 ... 但是,Mondrian 4.x似乎并未得到Mondrian核心维护者的积极开发,因此我们已将其作为依赖项而放弃。 支持4.x模式的mond
  • Mondrian WEB 嵌入

    2018-11-06 09:58:15
    Mondrian WEB 嵌入,介绍开源 OLAP 引擎,介绍如何入门mondiran
  • Mondrian实例

    热门讨论 2014-04-17 21:36:14
    这个Java实例将利用Mondrian提供的OLAP引擎对已建立好的数据立方体XML进行MDX查询。不是网上到处都有的jPivot,而是一个更基础更轻量的例子。
  • mondrian 源码

    2015-04-26 13:09:55
    mondrian源码 及js 连接xmla ,配置 datasource及shema文件
  • [Manning Publications] Mondrian 实战 英文版 [Manning Publications] Mondrian in Action E Book ☆ 出版信息:☆ [作者信息] William Back D Nicholas Goodman Julian Hyde [出版机构] Manning ...
  • 蒙德里安Java Piet Mondrian艺术在Java中
  • 介绍 Mondrian OLAP 引擎的使用方法,官方书籍,原版书卖500大洋。
  • mondrian配置例子

    2015-09-24 09:23:35
    mondrian配置例子,附件是openi源码例子,集成了mondrian+Jpivot。
  • olap mondrian

    2015-11-02 16:30:24
    Mondrian is an OLAP (online analytical processing) engine written in Java. It reads from JDBC data sources, aggregates data in a memory cache, and implements the MDX language and the olap4j and XML/A ...
  • Mondrian异常

    2015-10-23 08:12:33
    Mondrian异常

    由于要做多维报表的展现,需要使用OLAP的引擎Mondrian,于是最近一直在学习MDX查询语言,在做Demo时遇到了很多bug,我认为这些异常对于初学MDX查询语言的朋友来说很常见,一般都会遇到这些bug,这里我将自己遇到的bug收集起来,同时将其解决方法一并记录下来,希望遇到同样问题的朋友可以参考一下,希望可以节省一些你调试此类bug的时间。

     

     

    异常: 1

     [JPivot] 15 七月 2010 10:10:36,312 ERROR [Session FC17340B57820BEB01CC6F6D86DAE1E6] com.tonbeller.jpivot.tags.OlapModelTag#doEndTag:

    com.tonbeller.jpivot.olap.model.OlapException: Mondrian Error:All arguments to function &apos;{}&apos; must have same hierarchy.

     

    解决方案:

    问题是集合(Set)中的成员不在同一个层次里,比如写成

    select {[Measures].[总销售额],[Measures].[贡献度]} ON columns,

      {[产品类别].[所有产品],[客户性别].[所有性别]} ON rows

    from [Sales]

     

          由于“产品类别”和“客户性别”是两个不同的维度,而MDX的基本特性3—集合(Set),它的特点是集合里可以含有若干个Member,但是必须是同一维度上的Member,如{[Time].[1996],[Time].[1997]};

    也可以是Cube上的若干个Tuple的集合,同样要注意的是,这些Tuple集合的子集之间存在严格的维度对称关系,如{([Computers].[China]),([Air_Conditioner].[Jpan])}.

     

     

    小知识点说明:

     

    [销售季度].[所有季度] [销售季度].children的区别:

    如下面的例子:

     

     

     

    select {[销售季度].[所有季度]} ON columns,

     

      {[产品类别].CHILDREN} ON rows

         from [Sales]

     

    select {[销售季度].CHILDREN} ON columns,

      {[产品类别].CHILDREN} ON rows

         from [Sales]

     

    的区别是:

     

    首先,前者是一个Member,后者是一个集合(Set),因此在使用时,特别是放在一个Set中使用时要特别注意,否则会报我上面所说的异常1。

    其次,两者显示出来的效果图也是不一样的,在页面上,前者点击“所有季度”后才会展现所有季度;而后者是直接将“第一季度,第二季度,第三季度,第四季度”依次显示在页面客户面前,不能按层次收缩。

     

     

     

     

     

     

    异常: 2

    mondrian.olap.MondrianException: Mondrian Error:Named set in cube &apos;Sales&apos; has bad formula

    Caused by: mondrian.olap.MondrianException: Mondrian Error:Error while parsing MDX statement &apos;WITH

    MEMBER [Measures].[平均单价]

      AS &apos;[Measures].[总销售额] / [Measures].[数量]&apos;,

    FORMAT_STRING = "¥#,##0.00",

    [$member_scope] = &apos;CUBE&apos;,

    MEMBER_ORDINAL = 2

    MEMBER [Measures].[贡献度]

      AS &apos;([Measures].[总销售额],[所有类别].CURRENTMEMBER) / ([Measures].[总销售额],[所有类别].[所有产品])&apos;,

    FORMAT_STRING = "#%",

    [$member_scope] = &apos;CUBE&apos;,

    MEMBER_ORDINAL = 3

    SELECT FROM [Sales]&apos;

        at mondrian.resource.MondrianResource$_Def0.ex(MondrianResource.java:785)

        at mondrian.olap.Parser.parseInternal(Parser.java:759)

        at mondrian.olap.ConnectionBase.parseQuery(ConnectionBase.java:74)

        ... 59 more

    Caused by: mondrian.olap.MondrianException: Mondrian Error:MDX object &apos;[所有类别]&apos; not found in cube &apos;Sales&apos;

     

     

    解决方法:

    这个问题报错是由于解析MDX查询语句时发现问题解析不了。

    一般遇到这个错就是MDX查询语句中的维度和schema文件tezz.xml里定义的拼写的不一致,或者就是单词拼写错误,我的错误是就是在schema文件里定义calculator时名称写的不一致。

     

     

     

    异常: 3

    Caused by: mondrian.olap.MondrianException: Mondrian Error:Error while parsing MDX statement &apos;

     

    select {[Measures].[数量]} ON columns,

              {([产品类别].[所有产品]),([销售季度].[第一季度])} ON rows

           from [Sales]

    &apos;

        at mondrian.resource.MondrianResource$_Def0.ex(MondrianResource.java:785)

        at mondrian.olap.Parser.parseInternal(Parser.java:759)

        at mondrian.olap.ConnectionBase.parseQuery(ConnectionBase.java:74)

        ... 47 more

    Caused by: mondrian.olap.MondrianException: Mondrian Error:Internal error: while building member cache; sql=[select "Quarter"."quarterId" as "c0", "Quarter"."quarterName" as "c1" from "Month" as "Month", "Quarter" as "Quarter" where "Month"."quarterId" = "Quarter"."quarterId" and UPPER("Quarter"."quarterName") = UPPER(&apos;第一季度&apos;) group by "Quarter"."quarterId", "Quarter"."quarterName" order by "Quarter"."quarterId" ASC]

     

     

    解决方法:

         从异常信息可以看出解析MDX语句时发生错误,这个错是由于我表与表之间的关系在schema文件tezz.xml中定义的不对,以至于解析出的sql里出现了字段错位到别的表里去了。将各表间关系定义正确了就可以了。

     

     

     

     

    异常: 4

    [JPivot] 19 七月 2010 15:19:29,656 ERROR [Session ] com.tonbeller.jpivot.tags.OlapModelTag#doEndTag:

    com.tonbeller.wcf.controller.EmptyThreadLocalStackException

    org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspException: org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspException: com.tonbeller.wcf.controller.EmptyThreadLocalStackException

        org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:522)

        org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:398)

        org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)

        org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)

        javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

     

     

    页面报的异常为:

    org.apache.jasper.JasperException: An exception occurred processing JSP page/test/param1.jsp at line 23:

     20:

     21:Click on a Region.

     22:<p>

     23:<wcf:include id="include01" httpParam="query" prefix="/WEB-INF/queries/" suffix=".jsp"/>

     24: 

      25:<from action="param1.jsp" method="post" id="form01">

      26:

     

     

     

    解决方案:

         这个异常耽误了我和同事半天的时间,从控制台和页面信息都找不出错误原因,上网查资料,是有这个异常,我是中英文的网页资料说明都看了,就是没看到解决方法。最后,还是同事的另外一个异常给了我提示,于是我去web.xml文件中查看,果然是里面配置出现了问题。

         将web.xml中的filter的url­-pattern值由“testpage.jsp”改为“*.jsp” 即可!

     

    我之前的web.xml里filter的配置如下:

    <filter>

        <filter-name>JPivotController</filter-name>

        <filter-class>com.tonbeller.wcf.controller.RequestFilter</filter-class></filter>

      <filter-mapping>

        <filter-name>JPivotController</filter-name>

        <url-pattern>testpage.jsp</url-pattern>

      </filter-mapping>

     

     

     

     

    异常: 5

    [JPivot] 20 七月 2010 13:59:00,218 ERROR [Session E2F53D86EE225E320A412091BF8E28D9] com.tonbeller.wcf.controller.RequestFilter#doFilter: Error handling request

    com.tonbeller.jpivot.olap.model.OlapException: Mondrian Error:No function matches signature &apos;Parameter(<String>, <Dimension>)&apos;

        at com.tonbeller.jpivot.mondrian.MondrianModel.initialize(MondrianModel.java:550)

     

    解决方案: Parameter 方法有错,其参数好像不能为2个,我改成了3个异常就解决了,bug虽解决了了,但对Parameter的使用及里面的各个参数的作用和意义都不清楚,网上也没找到资料,要是哪位朋友知道的话请不惜赐教一下:

     

    将下面代码中的查询:

    <jp:mondrianQuery id= "paramquery01" catalogUri= "/WEB-INF/queries/tezz.xml"

        jdbcDriver= "net.sourceforge.jtds.jdbc.Driver"

        jdbcUrl= "jdbc:jtds:sqlserver://localhost:1433/Tezz" jdbcUser= "sa"

    jdbcPassword= "123">

    select

     {[Measures].[数量],[Measures].[平均单价],[Measures].[总销售额]} ON columns,

     {Parameter("ProductMember", [产品类别])} ON rows

    from [Sales]

    </jp:mondrianQuery>

     

    改为:

    select

     {[Measures].[数量],[Measures].[平均单价],[Measures].[总销售额]} ON columns,

     {Parameter("ProductMember", [产品类别],[产品类别].[数码])} ON rows

    from [Sales]

     

     

     

     

     

    异常: 6

     

    [JPivot] 20 七月 2010 14:05:45,781 ERROR [Session D24F8131994DE11BA5856AC44236BD90] com.tonbeller.wcf.controller.RequestFilter#doFilter:Error handling request

    com.tonbeller.jpivot.olap.navi.ExpressionParser$InvalidSyntaxException: [????].[????].[??].[???]

        at com.tonbeller.jpivot.mondrian.MondrianExpressionParser.parse(MondrianExpressionParser.java:121)

        at com.tonbeller.jpivot.param.SetParameterTag.setQueryParam(SetParameterTag.java:93)

     

    解决方案:异常原因是中文乱码,建议1:改成英文的,建议2:加个过滤器,我暂时使用的是方法1,方法2加过滤器没成功,在web.xml中加上如下代码:

    <filter>

        <filter-name>Set Character Encoding</filter-name>

        <filter-class>com.tonbeller.wcf.charset.CharsetFilter</filter-class>

        <init-param>

            <param-name>encoding</param-name>

            <param-value>UTF-8</param-value>

        </init-param>

      </filter>

     

      <filter-mapping>

        <filter-name>Set Character Encoding</filter-name>

        <url-pattern>/*</url-pattern> 

      </filter-mapping>

     

          也许还要进行其他设置,目前我还没找到解决的方法。

    异常:8

     

    [JPivot] 21 七月 2010 23:26:31,109 ERROR [Session 3DA5B31A164F01E50C42D796D221BC2F] com.tonbeller.jpivot.tags.OlapModelTag#doEndTag:

    mondrian.olap.MondrianException: Mondrian Error:Named set in cube &apos;Sales&apos; has bad formula

    .

    Caused by: mondrian.olap.MondrianException: Mondrian Error:No function matches signature &apos;<Level>.prevMember&apos;

     

     

    解决方法:这个异常可以参看异常15。

     

     

    %***************************************************************************

     

    异常:9

     

     

    33031 [http-8088-2] ERROR com.tonbeller.wcf.controller.RequestFilter  - Error handling request

    javax.servlet.ServletException: javax.servlet.jsp.JspException: com.tonbeller.jpivot.olap.model.OlapException: Mondrian Error:Syntax error at line 1, column 59, token &apos;EOF&apos;

    Caused by: mondrian.olap.MondrianException: Mondrian Error:Syntax error in MDX expression &apos;IsAncestor([Sale Region].CurrentMember,[Sale Region].[suzhou]&apos;

        at mondrian.resource.MondrianResource$_Def0.ex(MondrianResource.java:785)

     

    解决方法:待解决

     

     

    %***************************************************************************

     

     

     

     

    异常:10

    Caused by: com.tonbeller.jpivot.olap.model.OlapException: Mondrian Error:Tuple contains more than one member of dimension &apos;[Product Category]&apos;.

        at com.tonbeller.jpivot.mondrian.MondrianModel.initialize(MondrianModel.java:550)

     

    解决方法:

    由于我粗心,将“.”误写成了“,”,才会报上面异常。修改方法为将“[Product Category],[All Products]”改为“[Product Category].[All Products]”。

    select {[Measures].[ROI],[Measures].[Number],Measures.[Number Proportion],[Measures].[Average UnitPrice],[Measures].[Total Sale],[Measures].[Product Percentage]} ON columns, NON EMPTY

      {([Product Category],[All Products],[Customer Sex].[All Sex])} ON rows from [Sales]

     

     

    %***************************************************************************

    异常:11

     

    2474343 [http-8080-2] ERROR com.tonbeller.jpivot.tags.OlapModelTag  -

    mondrian.olap.MondrianException: Mondrian Error:Internal error: Error while creating SQL dialect

        at mondrian.resource.MondrianResource$_Def0.ex(MondrianResource.java:785)

        at mondrian.olap.Util.newInternal(Util.java:1340)

        at java.lang.Thread.run(Thread.java:619)

    Caused by: java.sql.SQLException: Network error IOException: Connection refused: connect

     

     

    解决方法:

    由异常信息可看出出现此异常是由于连接数据库出错,我仔细检查了是由于将mysql数据库连接成了SqlServer数据库。

     

     

    %***************************************************************************

     

    异常:12

     

    154157 [http-8080-1] ERROR com.tonbeller.wcf.controller.RequestFilter  - exeption

    org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspException: OlapModel/Query ${paramquery01} not found

        at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:522)

     

     

    解决方法:

    错误原因是以下代码中:

    <jp:setParam query="${paramquery01}" httpParam= "param" mdxParam= "ProductMember">

    <jp:mondrianQuery id="query01"

        jdbcDriver="com.mysql.jdbc.Driver"

        jdbcUrl="jdbc:mysql://localhost:3306/tezz?user=root&password=sys"

        catalogUri="/WEB-INF/queries/tezz.xml" >

    select

     {[Measures].[Number],[Measures].[Average UnitPrice],[Measures].[Total Sale]} ON columns,

     {Parameter("ProductMember", [Product Category],[Product Category].[All Products])} ON rows

    from [Sales]

    </jp:mondrianQuery>

    </jp:setParam>

     

    jpivot的setParam标签的query属性值就是mondrianQuery标签的id属性值,应一致。将query01改为paramquery01即可。

     

    %***************************************************************************

    异常:13

     

    信息: SessionListener: contextInitialized()

    2010-7-23 8:44:12 org.apache.catalina.session.StandardManager doLoad

    严重: IOException while loading persisted sessions: java.io.EOFException

    java.io.EOFException

        at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2281)

        at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2750)

        at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:780)

        at java.io.ObjectInputStream.<init>(ObjectInputStream.java:280)

        at org.apache.catalina.util.CustomObjectInputStream.<init>(CustomObjectInputStream.java:58)

     

     

     

    解决办法:重建项目换个项目名称。

     

    %***************************************************************************

    异常:14

     

    87875 [http-8088-1] ERROR com.tonbeller.wcf.controller.RequestFilter  - exeption

     

    页面异常

    org.apache.jasper.JasperException: An exception occurred processing JSP page /testpage.jsp at line 44

     

    41: <form action="testpage.jsp" method="post">

    42:

    43: <%-- include query and title, so this jsp may be used with different queries --%>

    44: <wcf:include id="include01" httpParam="query" prefix="/WEB-INF/queries/" suffix=".jsp"/>

    45: <c:if test="${query01 == null}">

    46:   <jsp:forward page="/index.jsp"/>

    47: </c:if>

     

     

    Caused by: com.tonbeller.jpivot.olap.model.OlapException: Mondrian Error:No function matches signature &apos;(<Set>, <Member>)&apos;

        at com.tonbeller.jpivot.mondrian.MondrianModel.initialize(MondrianModel.java:550)

        at com.tonbeller.jpivot.olap.model.OlapModelDecorator.initialize(OlapModelDecorator.java:132)

     

    解决方法:

    我的mdx查询语句如下:

     

    select {[Measures].[Total Sale],[Measures].[Product Percentage]} ON columns,

      {([Product Category].[All Products].children,[Customer Sex].[All Sex])} ON rows

    from [Sales]

     

    改为:select {[Measures].[Total Sale],[Measures].[Product Percentage]} ON columns,

      {([Product Category].[All Products],[Customer Sex].[All Sex])} ON rows

    from [Sales]

     

    即可。

     

     

    %***************************************************************************

    异常:15

     

    1317609 [http-8088-1] ERROR com.tonbeller.wcf.controller.RequestFilter  - cause

    javax.servlet.ServletException: javax.servlet.jsp.JspException: org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspException: com.tonbeller.jpivot.olap.model.OlapException: Mondrian Error:No function matches signature &apos;{<Level>}&apos;

        at org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:858)

     

    Caused by: com.tonbeller.jpivot.olap.model.OlapException: Mondrian Error:No function matches signature &apos;{<Level>}&apos;

        at com.tonbeller.jpivot.mondrian.MondrianModel.initialize(MondrianModel.java:550)

        at com.tonbeller.jpivot.olap.model.OlapModelDecorator.initialize(OlapModelDecorator.java:132)

     

    解决方案:

    我的mdx查询语句:

    select {[Sale Time].[quarterName] } ON columns,

      {[Product Category].[All Products].CHILDREN} ON rows

         from [Sales]

    由于[Sale Time].[quarterName]只是到了级别(level),而集合set中只能是member或者tuple,

    故只需将{[Sale Time].[quarterName]}改为{[Sale Time].[quarterName].AllMembers}

    效果图为:

     

     

     

    {[Sale Time].[quarterName].AllMembers}与{[quarterName].AllMembers}得出的效果一样。

     

    若改为:{[Sale Time] },则效果图为:

     

     

     

    若改为:{[Sale Time].[quarterName].children},则报异常:

    Caused by: javax.servlet.ServletException: javax.servlet.jsp.JspException: com.tonbeller.jpivot.olap.model.OlapException: Mondrian Error:No function matches signature &apos;<Level>.children&apos;

        at org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:858)

    同样,{[Sale Time].[quarterName].children}与{[quarterName].children}效果是一样的。

     

     

     

     

    故我得出的结论是:

     

    1. level下面不能调用children,只能用allmembers来获得子集所有成员。Children可以用在层次hierarchy下面如:[Product Category].[All Products].children(注意的是这里的”All Products”是层次的allMemberName属性,而非name属性,用name属性的写法是[Sale Time.OnlyQ].children,此时也可以用allmembers);也可以直接在维度下面,如[Sale Time].children,显示效果图为:

     

    同时,allmembers也可以用在直接维度下面如[Sale Time]. allmembers,显示效果图为将成员全部列出,不是下钻(drill-down)形式,操作只能是上卷(drill-up):

     

    结论2:两个嵌套的level的(name属性)不能同时用,即[yearName].[quarterName]会报找不到的错误,但涉及到具体的members就可以用,如[2007].[Q1].

     

    涉及到具体member值如[2007],或[2007].[Q1]等的member,后面就不能使用member,allmembers,currentmember,都会报上面的同样的错,但可以使用如下术语:

    Children,firstchild,parent,prevmember, nextmember。

    展开全文
  • Mondrian简介

    千次阅读 2019-07-17 10:38:45
    一、 Mondrian简介 Mondrian是一个开源项目。一个用Java写成的OLAP引擎。它用MDX语言实现查询,从关系数据库(RDBMS)中读取数据。然后经过javaAPI以多维的方式对结果进行展示。 Mondrian的使用方式同JDBC驱动类似。...

    出自:https://www.cnblogs.com/lk-fxtx/p/7067720.html

    一、  Mondrian简介

    Mondrian是一个开源项目。一个用Java写成的OLAP引擎。它用MDX语言实现查询,从关系数据库(RDBMS)中读取数据。然后经过java API以多维的方式对结果进行展示。

    Mondrian的使用方式同JDBC驱动类似。可以非常方便的与现有的Web项目集成

    1.1 Mondrian的体系结构(Architecture)

    Mondrian OLAP 系统由四个层组成; 从最终用户到数据中心, 顺序为: 
    1.1.1 表现层(the presentation layer)
    1.1.2 维度层(the dimensional layer)
    1.1.3 集合层(the star layer)
    1.1.4 存储层(the storage layer)
    结构图如下:

     

     

    1.1.1 表现层(the presentation layer)

    表现层决定了最终用户将在他们的显示器上看到什么, 及他们如何同系统产生交互。

    有许多方法可以用来向用户显示多维数据集, 有 pivot 表 (一种交互式的表), pie, line 和图表(bar charts)。它们可以用Swing 或 JSP来实现。

    表现层以多维"文法(grammar)(维、度量、单元)”的形式发出查询,然后OLAP服务器返回结果。

    1.1.1.1 Jpivot表现层

    JPivot 是Mondrian的表现层TagLib,一直保持着良好的开发进度。

    您可以通过访问jpivot的官方网站http://jpivot.sourceforge.net/以获得更多的帮助及支持

    jpivot使用XML/ XSLT渲染OLAP报表:

    JPivot 使用 WCF (Web Component Framework)  ,基于XML/XSLT来渲染Web UI组件。这使它显得十分另类。不过,OLAP报表这种非常复杂但又有规律可循的东西,最适合使用XSLT来渲染。

    jpivot完全基于JSP+TagLib:

    JPivot另外一个可能使人不惯的地方是它完全基于taglib而不是大家熟悉的MVC模式。

    但它可以很方便的将多维数据展示给最终用户,如下表格:

     

     

    jpivot其实是一个自定义jsp的标签库。它基于XML/XSLT配置来生成相应的html。所幸的是,我们并不需要了解太多关于这方面的内容,我们只要掌握相应jsp标签的使用即可。

    在本教程的实例中,我们将会对一些常用到的jpivot标签进行讲解。

    您还可以通过汉化WEB-INF/jpivot下的xml文件来完成对jpivot的汉化工作

    1.1.2 维度层(the dimensional layer)

    维度层用来解析、验证和执行MDX查询要求。

    一个MDX查询要通过几个阶段来完成:首先是计算坐标轴(axes),再者计算坐标轴axes 中cell的值。

     为了提高效率,维度层把要求查询的单元成批发送到集合层,查询转换器接受操作现有查询的请求,而不是对每个请求都建立一个MDX 声明。

    1.1.3 集合层(the star layer)

    集合层负责维护和创建集合缓存,一个集合是在内存中缓存一组单元值, 这些单元值由一组维的值来确定。

    维度层对这些单元发出查询请求,如果所查询的单元值不在缓存中,则集合管理器(aggregation manager)会向存储层发出查询请求

    1.1.4 存储层(the storage layer)

    存储层是一个关系型数据库(RDBMS)。它负责创建集合的单元数据,和提供维表的成员。

    1.2 API

    Mondrian 为客户端提供一个用于查询的API

    因为到目前为止,并没有一个通用的用于OLAP查询的API,因此Mondrian提供了它私有的API.

    尽管如此,一个常使用JDBC的人将同样发现它很熟悉.不同之处仅在于它使用的是MDX查询语言,而非SQL

    下面的java片段展示了如何连接到Mondrian,然后执行一个查询,最后打印结果.

    [java] view plaincopy

    1. import mondrian.olap.*;  
    2.     import java.io.PrintWriter;  
    3.     Connection connection = DriverManager.getConnection("Provider=mondrian;"   
    4.             +"Jdbc=jdbc:odbc:MondrianFoodMart;"   
    5.             +"Catalog=/WEB-INF/FoodMart.xml;",null,false);  
    6.     Query query = connection.parseQuery("SELECT {[Measures].[Unit Sales], [Measures].[Store Sales]} on columns,"   
    7.             +" {[Product].children} on rows "   
    8.             +"FROM [Sales] " +"WHERE ([Time].[1997].[Q1], [Store].[CA].[San Francisco])");  
    9.     Result result = connection.execute(query);  
    10. 10.     result.print(new PrintWriter(System.out));  

    与JDBC类似,一个Connection由DriverManager创建,Query 对象类似于JDBC 的Statement,它通过传递一个MDX语句来创建.Result对象类似于JDBC的ResultSet,只不过它里面保存的是多维数据

    您可以通过查看Mondrian帮助文档里的javadoc来获取更多关于Mondrian API的资料

    通过上面的介绍,您应该对mondrian的体系有一个基本的了解。

    Mondrian安装完成后,便可直接使用自带的Derby数据库中的数据进行测试和学习。

    我们看一个最简单的MDX语句:

    select

    {

    [Measures].[Unit Sales],

    [Measures].[Store Cost],

    [Measures].[Store Sales]

    } ON COLUMNS,

    {(

    [Promotion Media].[All Media],

    [Product].[All Products]

    )} ON ROWS

    from [Sales]

    where [Time].[1997]

     

    其中,SELECT 后跟着的是测量指和维度,[Measures]是指测量值,也就是报表中的指标,[Promotion Media]、[Product]、[Time]是指维度,也就是我们需要挖掘的维度。我们发现,WHERE后面也是跟着维度的,代表从维度中过滤出一些数据。

    FROM后面跟着的是立方体,[Sales]是我们OLAP中建立的数据立方体。

    好了,我们一步步看看这个DMX语句后面配置的Schema吧,Schema这个怎么翻译好呢,我估计协议比较妥当,因为它就只是XML定义的协议。

     

    首先,看from后跟的数据立方体,Sales

    <!-- 

        定义立方体 

        name 立方体名称

        defaultMeasure 默认测量值

    -->

    <Cube name="Sales" defaultMeasure="Unit Sales">

    <!-- 定义table,也就是表,使用name指定表名 -->

        <Table name="sales_fact_1997">

        </Table>

    </Cube>

     

    <!--

    定义度量值

    name 度量的名称,用于select

    column 对应的表的列

    aggregator 聚合函数

    formatString 格式化字符串,可以格式化类似Money、时间之类的格式

    -->

    <Measure name="Unit Sales" column="unit_sales" aggregator="sum" formatString="Standard"/>

     

    <!--

    定义维度

    name 维度名称,用于Select

    foreignKey 外键id

    -->

    <Dimension name="Promotion Media" foreignKey="promotion_id">

    <!--

    定义维度的层次

    hasAll 是否包含所有的维度

    allMemberName 所有维度的名称

    primaryKey 翻译表的主键

    defaultMember 默认维度,可以为allMemberName

    -->

    <Hierarchy hasAll="true" allMemberName="All Media" primaryKey="promotion_id" defaultMember="All Media">

    <!-- 指定翻译表 -->

    <Table name="promotion"/>

    <!--

    定义层次的水平,也就是调用维度的哪个字段来表现维度

    name

    -->

    <Level name="Media Type" column="media_type" uniqueMembers="true"/>

    </Hierarchy>

    </Dimension>

     

    <!--

    维度复用

    name 维度名称,用于Select

    foreignKey 外键id

    source 来源,也就是参考其他立方体中的Dimension

    -->

    <DimensionUsage name="Product" source="Product" foreignKey="product_id"/>

    <!--

    查看具体的Product维度的定义

    name 维度名称,一样的使用于Select

    -->

    <Dimension name="Product">

    <!--

    定义维度的层次

    hasAll 是否包含所有的维度

    allMemberName 所有维度的名称

    primaryKey 翻译表的主键

    defaultMember 默认维度,可以为allMemberName

    primaryKeyTable 主键的表名

    -->

    <Hierarchy hasAll="true" primaryKey="product_id" primaryKeyTable="product">

    <Join leftKey="product_class_id" rightKey="product_class_id">

    <Table name="product"/>

    <Table name="product_class"/>

    </Join>

     <!--

    第一个层次

    产品的总类

    name 层次的名称

    table 层次的表名

    column 对应的列

    uniqueMembers 成员是否唯一

     -->

    <Level name="Product Family" table="product_class" column="product_family" uniqueMembers="true"/>

    <Level name="Product Department" table="product_class" column="product_department" uniqueMembers="false"/>

    <Level name="Product Category" table="product_class" column="product_category" uniqueMembers="false"/>

    <Level name="Product Subcategory" table="product_class" column="product_subcategory" uniqueMembers="false"/>

    <Level name="Brand Name" table="product" column="brand_name" uniqueMembers="false"/>

    <Level name="Product Name" table="product" column="product_name" uniqueMembers="true"/>

    </Hierarchy>

    </Dimension>

    <!--

    最后,学习一个where语句中的时间维度的设定

    type 维度类型,这里是TimeDimension 时间维度

    -->

    <Dimension name="Time" type="TimeDimension">

    <Hierarchy hasAll="false" primaryKey="time_id">

    <Table name="time_by_day"/>

    <Level name="Year" column="the_year" type="Numeric" uniqueMembers="true" levelType="TimeYears"/>

    <Level name="Quarter" column="quarter" uniqueMembers="false" levelType="TimeQuarters"/>

    <Level name="Month" column="month_of_year" uniqueMembers="false" type="Numeric" levelType="TimeMonths"/>

    </Hierarchy>

    <Hierarchy hasAll="true" name="Weekly" primaryKey="time_id">

    <Table name="time_by_day"/>

    <Level name="Year" column="the_year" type="Numeric" uniqueMembers="true" levelType="TimeYears"/>

    <Level name="Week" column="week_of_year" type="Numeric" uniqueMembers="false" levelType="TimeWeeks"/>

    <Level name="Day" column="day_of_month" uniqueMembers="false" type="Numeric" levelType="TimeDays"/>

    </Hierarchy>

    </Dimension>

     

    看完以上Schema的协议定义,我们就可以把这个例子需要的协议文件最小化了,在${apache-tomcat-7.0.29}\webapps\mondrian\WEB-INF\queries\目录下新建一个XML文件TestSchema.xml,内容如下:

    <?xml version="1.0"?>

    <Schema name="Test">

    <Dimension name="Product">

    <Hierarchy hasAll="true" primaryKey="product_id" primaryKeyTable="product">

    <Join leftKey="product_class_id" rightKey="product_class_id">

    <Table name="product"/>

    <Table name="product_class"/>

    </Join>

    <Level name="Product Family" table="product_class" column="product_family" uniqueMembers="true"/>

    <Level name="Product Department" table="product_class" column="product_department" uniqueMembers="false"/>

    <Level name="Product Category" table="product_class" column="product_category" uniqueMembers="false"/>

    <Level name="Product Subcategory" table="product_class" column="product_subcategory" uniqueMembers="false"/>

    <Level name="Brand Name" table="product" column="brand_name" uniqueMembers="false"/>

    <Level name="Product Name" table="product" column="product_name" uniqueMembers="true"/>

    </Hierarchy>

    </Dimension>

    <Dimension name="Time" type="TimeDimension">

    <Hierarchy hasAll="false" primaryKey="time_id">

    <Table name="time_by_day"/>

    <Level name="Year" column="the_year" type="Numeric" uniqueMembers="true" levelType="TimeYears"/>

    <Level name="Quarter" column="quarter" uniqueMembers="false" levelType="TimeQuarters"/>

    <Level name="Month" column="month_of_year" uniqueMembers="false" type="Numeric" levelType="TimeMonths"/>

    </Hierarchy>

    <Hierarchy hasAll="true" name="Weekly" primaryKey="time_id">

    <Table name="time_by_day"/>

    <Level name="Year" column="the_year" type="Numeric" uniqueMembers="true" levelType="TimeYears"/>

    <Level name="Week" column="week_of_year" type="Numeric" uniqueMembers="false" levelType="TimeWeeks"/>

    <Level name="Day" column="day_of_month" uniqueMembers="false" type="Numeric" levelType="TimeDays"/>

    </Hierarchy>

    </Dimension>

    <Cube name="Sales" defaultMeasure="Unit Sales">

    <Table name="sales_fact_1997"></Table>

    <DimensionUsage name="Product" source="Product" foreignKey="product_id"/>

    <DimensionUsage name="Time" source="Time" foreignKey="time_id"/>

    <Dimension name="Promotion Media" foreignKey="promotion_id">

    <Hierarchy hasAll="true" allMemberName="All Media" primaryKey="promotion_id" defaultMember="All Media">

    <Table name="promotion"/>

    <Level name="Media Type" column="media_type" uniqueMembers="true"/>

    </Hierarchy>

    </Dimension>

    <Measure name="Unit Sales" column="unit_sales" aggregator="sum" formatString="Standard"/>

    <Measure name="Store Cost" column="store_cost" aggregator="sum" formatString="#,###.00"/> 

    <Measure name="Store Sales" column="store_sales" aggregator="sum" formatString="#,###.00"/>

    </Cube>

    </Schema>

     

    1.3 下载与发布

    下载地址:https://sourceforge.net/projects/mondrian/?source=typ_redirect

    点击files 里面有Mondrian的各种版本,其中mondrian-3.14.0是最新版本,mondrian-3.12.0是稳定版本。下载完成后就其解压,有2种部署方法。

     

     

    第一种方法:在解压后的文件中找到lib,打开里面有一个mondrian.war文件,将其直接扔到tomcat的webapps目录下,然后启动Tomcat,自动解压。打开浏览器输入localhost:8080/mondrian 出现欢迎界面说明部署成功。

    第一种方法:利用常用的ida开发工具。本次使用的是eclipse。

    打开eclipse新建一个Dynamic Web Project

     

     

    取名为Tezz,注意要勾上自动生成web.xml 选项

     

     

    然后添加必须的文件

    将下载的压缩包进行解压。完成后,进入文件夹可以看到如下目录结构。双击进入lib文件夹。

     

     

    Lib文件夹有如下内容:注意到这里的mondrian.war文件是一个可直接布署的项目,我们需要将它解压,然后从中取出我们所需要的文件。(建议将其扩展名改成zip,然后直接右键解压)

     

     

    进入解压后的文件夹,选中jpivot、wcf二个文件夹及busy.jsp、error.jsp、testpage.jsp三个文件,我们需要将这些资源复制到我们测试项目的WebRoot文件夹中。按ctrl+C键复制。

     

     

    注:jpivot、wcf这两个文件夹包含mondrian使用的图像和css文件。Busy.jsp显示等待页面、error.jsp显示出错页面、testpage.jsp这文件的用处将在后面介绍。

    切换到eclipse界面,在我们的Tezz项目的WebRoot文件夹处右击鼠标,在弹出的菜单中选择Paste(粘贴)即可

     

     

    粘贴完成后的项目结构如下

     

     

    注意:因为我们还未将所有资料复制到项目中,因此eclipse会显示错误图标

    最后进入WEB-INF文件夹(在上面步骤中解压的项目文件mondrian.war里),选中jpivot、lib、wcf这三个文件夹,同样需要复制它们到测试项目的WEB-INF文件夹中。

     

     

    Jpivot、wcf这两个文件夹包含jpivot和wcf用于生成用户界面的配置文件(*.xml、*.xsl)及标签文件(*.tld)的定义。Lib文件夹包含的是mondrian所要用的java包。

    切换到eclipse界面,在我们的Tezz项目的WebRoot文件夹处右击鼠标,在弹出的菜单中选择Paste(粘贴)

     

     

    至此Mondrian的支持添加完毕,下面我们将配置web.xml,让我们的项目能够使用到mondrian的功能。

    接下来我们需要配置的是web.xml

    过滤器(filter)

    复制如下所示的xml代码到我们测试项目Tezz的web.xml文件中。

    作用:这个过滤器在访问/testpage.jsp前被调用。它被设计成jpivot的前端控制器,用于判断并将用户的请求发送到某个页面。

    注:在实际项目中可以使用您自己定义的servlet或使用其他技术来替代它以提供更多的功能

    1.  <filter>  
    2.     <filter-name>JPivotController</filter-name>  
    3.     <filter-class>com.tonbeller.wcf.controller.RequestFilter</filter-class>  
    4.     <init-param>  
    5.       <param-name>indexJSP</param-name>  
    6.       <param-value>/index.html</param-value>  
    7.       <description>如果这是一个新的会话,则转到此页面</description>  
    8.     </init-param>  
    9.     <init-param>  
    10. 10.       <param-name>errorJSP</param-name>  
    11. 11.       <param-value>/error.jsp</param-value>  
    12. 12.       <description>出错时显示的页面</description>  
    13. 13.     </init-param>  
    14. 14.     <init-param>  
    15. 15.       <param-name>busyJSP</param-name>  
    16. 16.       <param-value>/busy.jsp</param-value>  
    17. 17.       <description>这个页面用于当用户点击一个查询时,在这个查询还未将结果还回给用户时所显示的界面</description>  
    18. 18.     </init-param>  

    19. </filter>  

    1. 20.   
    2. 21.   <filter-mapping>  
    3. 22.     <filter-name>JPivotController</filter-name>  
    4. 23.     <url-pattern>/testpage.jsp</url-pattern>  
    5. 24.   </filter-mapping>  

    Print  servlet,该servlet用于将数据生成Excel文件或pdf文件并返回给用户,如果您需要用到该功能,则需要将其copy到您项目的web.xml文件中

    1. <servlet>  
    2.     <servlet-name>Print</servlet-name>  
    3.     <display-name>Print</display-name>  
    4.     <description>Default configuration created for servlet.</description>  
    5.     <servlet-class>com.tonbeller.jpivot.print.PrintServlet</servlet-class>  
    6.   </servlet>  
    7.  <servlet-mapping>  
    8.     <servlet-name>Print</servlet-name>  
    9.     <url-pattern>/Print</url-pattern>  
    10. 10.   </servlet-mapping>  

    MDXQueryServlet用于接受并执行一个MDX查询,然后将该查询以Html表格的形式返回。其中的参数connectString用于指定连接到数据库的字符串,例如使用jtds驱动连接到sql server 2000的字符串如下:

    Provider=mondrian;Jdbc=jdbc:jtds:sqlserver://localhost/Tezz;user=sa;password=123456;Catalog=/WEB-INF/queries/tezz.xml;JdbcDrivers=net.sourceforge.jtds.jdbc.Driver; 

    如果您需要用到该功能,则需要将其copy到您项目的web.xml文件中。

    1. <servlet>  
    2.     <servlet-name>MDXQueryServlet</servlet-name>  
    3.     <servlet-class>mondrian.web.servlet.MDXQueryServlet</servlet-class>  
    4.     <init-param>  
    5.       <param-name>connectString</param-name>  
    6.       <param-value>@mondrian.webapp.connectString@</param-value>  
    7.     </init-param>  
    8.   </servlet>  
    9.  <servlet-mapping>  
    10. 10.     <servlet-name>MDXQueryServlet</servlet-name>  
    11. 11.     <url-pattern>/mdxquery</url-pattern>  
    12. 12.   </servlet-mapping>  

    DisplayChart 和GetChart 这两个Servlet 用于生成图表和将其显示给最终用户,如果您需要用到该功能,则需要将其copy到您项目的web.xml文件中。

    1. <!-- jfreechart provided servlet -->  
    2.   <servlet>  
    3.     <servlet-name>DisplayChart</servlet-name>  
    4.     <servlet-class>org.jfree.chart.servlet.DisplayChart</servlet-class>  
    5.   </servlet>  
    6.   <!-- jfreechart provided servlet -->  
    7.   <servlet>  
    8.     <servlet-name>GetChart</servlet-name>  
    9.     <display-name>GetChart</display-name>  
    10. 10.     <description>Default configuration created for servlet.</description>  
    11. 11.     <servlet-class>com.tonbeller.jpivot.chart.GetChart</servlet-class>  
    12. 12.   </servlet>  

    13. <servlet-mapping>  

    1. 14.     <servlet-name>DisplayChart</servlet-name>  
    2. 15.     <url-pattern>/DisplayChart</url-pattern>  
    3. 16.   </servlet-mapping>  

    17. <servlet-mapping>  

    1. 18.     <servlet-name>GetChart</servlet-name>  
    2. 19.     <url-pattern>/GetChart</url-pattern>  
    3. 20.   </servlet-mapping>  

    最后添加以下标签库到我们的web.xml项目中即可

    1. <taglib>  
    2.    <taglib-uri>http://www.tonbeller.com/wcf</taglib-uri>  
    3.    <taglib-location>/WEB-INF/wcf/wcf-tags.tld</taglib-location>  
    4.  </taglib>  
    5.   
    6.  <taglib>  
    7.    <taglib-uri>http://www.tonbeller.com/jpivot</taglib-uri>  
    8.    <taglib-location>/WEB-INF/jpivot/jpivot-tags.tld</taglib-location>  
    9.  </taglib>  

    至此,一个mondrian项目配置已经完成,下面就是写xml和jsp了

    如果使用的是Myeclipse的话需新建一个Web Project,注意需要加入JSTL支持

     

     

     

     

    剩余步骤和在Eclipse中一样

     

    1.4 测试用例

     

    下面贴出一个测试用例,以及中间遇见的问题供大家参考

     

    建表语句

     

    /**销售表*/  

    create table Sale (  

        saleId int not null,  

        proId int null,  

        cusId int null,   

        unitPrice float null,    --单价  

        number int null,     --数量  

        constraint PK_SALE primary key (saleId)  

    )  

        /**用户表*/  

    create table Customer (  

        cusId int not null,  

        gender char(1) null,    --性别  

        constraint PK_CUSTOMER primary key (cusId)  

    )  

    /**产品表*/  

    create table Product (  

        proId int not null,  

        proTypeId int null,  

       proName varchar(32) null,  

        constraint PK_PRODUCT primary key (proId)  

    )  

    /**产品类别表*/  

    create table ProductType (  

        proTypeId int not null,  

        proTypeName varchar(32) null,  

        constraint PK_PRODUCTTYPE primary key (proTypeId)  

    )  

     

    插入数据

     

    insert into Customer(cusId,gender) values(1,'F') 

    insert into Customer(cusId,gender) values(2,'M') 

    insert into Customer(cusId,gender) values(3,'M') 

    insert into Customer(cusId,gender) values(4,'F') 

    insert into producttype(proTypeId,proTypeName) values(1,'电器') 

    insert into producttype(proTypeId,proTypeName) values(2,'数码') 

    insert into producttype(proTypeId,proTypeName) values(3,'家具') 

    insert into product(proId,proTypeId,proName) values(1,1,'洗衣机') 

    insert into product(proId,proTypeId,proName) values(2,1,'电视机') 

    insert into product(proId,proTypeId,proName) values(3,2,'mp3')  

    insert into product(proId,proTypeId,proName) values(4,2,'mp4') 

    insert into product(proId,proTypeId,proName) values(5,2,'数码相机') 

    insert into product(proId,proTypeId,proName) values(6,3,'椅子') 

    insert into product(proId,proTypeId,proName) values(7,3,'桌子') 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(1,1,1,340.34,2) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(2,1,2,140.34,1) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(3,2,3,240.34,3) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(4,3,4,540.34,4) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(5,4,1,80.34,5) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(6,5,2,90.34,26) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(7,6,3,140.34,7) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(8,7,4,640.34,28) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(9,6,1,140.34,29) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(10,7,2,740.34,29) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(11,5,3,30.34,28) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(12,4,4,1240.34,72) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(13,3,1,314.34,27) 

    insert into sale(saleId,proId,cusId,unitPrice,number) values(14,3,2,45.34,27)

     

    建立模式(schema)文件

    简单的说,配置一个模式就是配置一个关系数据结构到多维数据结构的映射。就是创建一个xml文件来实现数据库表与多维数据源的对应关系,聚合,新增字段。

     

    在WEB-INFO目录下新建一个queries的文件夹,然后新建一个名为tse的XML文件,文件内容如下;注意Schema name 与 Cube name

     

    <?xml version="1.0" encoding="UTF-8"?>

    <Schema name="tse">

    <Cube name="Sales">

           <!-- 事实表(fact table) -->

           <Table name="SALE" />

           <!-- 客户维 -->

           <Dimension name="sex" foreignKey="CUSID">

                  <Hierarchy hasAll="true" allMemberName="allsex" primaryKey="CUSID">

                         <Table name="CUSTOMER"></Table>

                         <Level name="gender" column="GENDER"></Level>

                  </Hierarchy>

           </Dimension>

           <!-- 产品类别维 -->

           <Dimension name="good" foreignKey="PROID">

                  <Hierarchy hasAll="true" allMemberName="allgood" primaryKey="PROID" primaryKeyTable="PRODUCT">

                         <join leftKey="PROTYPEID" rightKey="PROTYPEID">

                                <Table name="PRODUCT" />

                                <Table name="PRODUCTTYPE"></Table>

                         </join>

                         <Level name="proTypeId" column="PROTYPEID"

                                nameColumn="PROTYPENAME" uniqueMembers="true" table="PRODUCTTYPE" />

                         <Level name="proId" column="PROID" nameColumn="PRONAME"

                                uniqueMembers="true" table="PRODUCT" />

                  </Hierarchy>

           </Dimension>

           <Measure name="quan1" column="NUMBER1" aggregator="sum" datatype="Numeric" />

           <Measure name="totalsell" aggregator="sum" formatString="¥#,##0.00">

                  <!-- unitPrice*number所得值的列 -->

                  <MeasureExpression>

                         <SQL dialect="generic">(UNITPRICE*NUMBER1)</SQL>

                  </MeasureExpression>

           </Measure>

           <CalculatedMember name="avgsell" dimension="Measures">

                  <Formula>[Measures].[totalsell] / [Measures].[quan1]</Formula>

                  <CalculatedMemberProperty name="FORMAT_STRING" value="¥#,##0.00" />

           </CalculatedMember>

    </Cube>

    </Schema>

     

     

    接着在该文件夹下建立一个同名的jsp文件,文件用来存储我们连接数据库的驱动,地址,用户名,密码和我们要使用的sql查询语句 示例如下:

     

    <%@ page session="true" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>

    <%@ taglib uri="http://www.tonbeller.com/jpivot" prefix="jp" %>

    <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

     

    <jp:mondrianQuery id="query01" jdbcDriver="oracle.jdbc.driver.OracleDriver" jdbcUrl="jdbc:oracle:thin:@localhost:1521:orcl" catalogUri="/WEB-INF/queries/tse.xml"

       jdbcUser="hlsoa" jdbcPassword="hlsoa" connectionPooling="false">

    select

      {[Measures].[quan1], [Measures].[avgsell], [Measures].[totalsell]} on columns,

      {([good].[allgood], [sex].[allsex])} ON rows

    from Sales

    </jp:mondrianQuery>

    <c:set var="title01" scope="session">Test Query uses Mondrian OLAP</c:set>

     

    如果是直接在Tomcat部署的话,打开浏览器输入http://localhost:8080/mondrian/testpage.jsp?query=tse就可以出现结果

    如果是通过IDE,打开浏览器输入http://localhost:8080/Tezz/testpage.jsp?query=tse

     

     

    1.5常见的错误与问题

    1.5.1数据库驱动和数据库连接问题

     

     

     

    报这个错误说明我们缺少oracle驱动jar包加载不了oracle驱动,此时我们可以从Oracle官网下载或者在以前的项目中复制一个过来放到WEB-INF下的lib文件夹中

     

     

     

     

    第二点要注意的是我们写在tse.jsp文件中的jdbcUrl,Driver一定不能写错,不要前后多出

    空格。同时cataloguri也要写成相对应的,用户名、密码同样不能出错。

     

     

    1.5.2 testpage.jsp attribute”test” with 报错问题

     

     

     

    解决方法:找到webapps下的testpage.jsp页面到到<c:if>query01这一段直接删除

     

     

     

    1.5.3执行SQl语句报错情景1(Oracle数据库特有问题)

     

     

     

    当时一切都改好了,就是在执行SQL语句是报错,将这段语句看了半天也没发现错误,在网上查找半天也没有解决方案,最后发现错误出现在cube文件中,因为本人使用的数据库是Oracle,所以cube文件里面所涉及到数据库字段的名称都要改成大写,这样mondrian才能够识别。这个问题耽误好长时间。。。。

     

     

    1.5.4 常见的乱码和字符集设置问题

    在jsp和xml文件中要与数据库的字符集保持一致,同时为了防止出现乱码问题,也可以借鉴作者的方法在jsp和xml文件中尽量避免出现中文。

     

     

    展开全文
  • De Stijl 由两位抽象艺术先驱Piet Mondrian和 Theo vanDoesburg 于 1917 年创立。 De Stijl 在荷兰语中意为风格。 演示 生成 Piet Mondrian 艺术。 有无数的选择。 控制 数以千计的美丽配色方案。 图片的自定义...
  • mondrian-3.5.0

    2015-07-03 14:53:09
    mondrian-3.5.0.jar 解决中文乱码问题
  • Mondrian In Action

    2014-05-16 16:03:48
    This book is about Mondrian 4.0 and related technologies. It’s organized into chap- ters based on functionality. Chapters are designed to be standalone in most cases, but it’s easier, especially for...
  • 基于Piet Mondrian的艺术随机生成视觉 ,我受到詹妮弗·迪瓦特(Jennifer Dewalt)的的第四天的启发,以学习有关Piet Mondrian的更多信息,并了解我是否可以编写代码来随机生成模仿他的风格的作品。 该代码还用作我...
  • mondrian基础

    2010-03-18 14:45:06
    mondrian基本概念及一些基础理论介绍
  • 欢迎来到蒙德里安 Mondrian是一种在线分析处理(OLAP)服务器,使业务用户能够实时分析大量数据。 子模块 mondrian -mondrian Java库的核心 工作台-用于生成Mondrian模式的桌面GUI
  • Mondrian系列

    2019-03-05 10:48:00
    1.Mondrian Schema Workbench 概念及常用参数 2.Schema Workbench 启动慢解决办法 3.自己写的第一个Schema文件 4.维度-退化维度 5.维度-共享维度 6.维度-层次维度 7.使用Mondrian Virtual OLAP Cube 实现星座...
  • kylin-mondrian-interaction, 关于Apache与 Pentaho Mondrian 交互的一些信息 Interaction InteractionKylin与 Mondrian 与Saiku的交互包括补丁和 jars 。预安装要求你应当能够运行 Kylin,构建和创建一个 Cube多维...
  • Mondrian+Oracle 实例

    2017-11-02 17:34:59
    Mondrian+Oracle 实例,及异常分析,功能介绍,连接数据库的各种方式等
  • Piet-Mondrian-Pattern-Generator 自动生成与 Piet Mondrian 作品风格相似的图案

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,764
精华内容 1,105
关键字:

mondrian