Mondrian 使用教程
http://blog.csdn.net/evangel_z/article/details/29585571
通過本教程,您將了解到什么是Mondiran,及如何將mondrian支持添加到您的Java Web項目中。
在閱讀本教程之前,您可能需要掌握以下概念:
OLAP(聯機分析處理On-Line Analytical Processing),您可以通過閱讀ROLAP的概念.pptx來了解OLAP
MDX多維表達式,您可以通過閱讀MDX的基本語法及概念.pptx來了解MDX
1. Mondrian是什么?
Mondrian是一個開源項目。一個用Java寫成的OLAP引擎。它用MDX語言實現查詢,從關系數據庫(RDBMS)中讀取數據。然后經過Java API以多維的方式對結果進行展示。
Mondrian的使用方式同JDBC驅動類似??梢苑浅7奖愕呐c現有的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,然后執行一個查詢,最后打印結果.
- import mondrian.olap.*;
- import java.io.PrintWriter;
- Connection connection = DriverManager.getConnection("Provider=mondrian;"
- +"Jdbc=jdbc:odbc:MondrianFoodMart;"
- +"Catalog=/WEB-INF/FoodMart.xml;",null,false);
- Query query = connection.parseQuery("SELECT {[Measures].[Unit Sales], [Measures].[Store Sales]} on columns,"
- +" {[Product].children} on rows "
- +"FROM [Sales] " +"WHERE ([Time].[1997].[Q1], [Store].[CA].[San Francisco])");
- Result result = connection.execute(query);
- result.print(new PrintWriter(System.out));
與JDBC類似,一個Connection由DriverManager創建,Query 對象類似于JDBC 的Statement,它通過傳遞一個MDX語句來創建.Result對象類似于JDBC的ResultSet,只不過它里面保存的是多維數據
您可以通過查看Mondrian幫助文檔里的javadoc來獲取更多關于Mondrian API的資料
通過上面的介紹,您應該對mondrian的體系有一個基本的了解。
下面我們將通過一個簡單的例子來加深您的理解。
2. 一個簡單的Mondrian例子
現在讓我們用一個簡單的例子來說明將Mondrian支持添加到您java web的具體步驟。
2.1 準備開發工具及環境
本測試需要的環境:
操作系統:Windows 2000;
Web服務器:tomcat6.0;
關系數據庫:sql server 2000;
開發工具:eclipse + myeclipse;
JDBC驅動:jtds-1.2.2;
您可以在http://tomcat.apache.org/上下載到tomcat的最新版本及幫助;
您可以在http://www.myeclipseide.com/上下載到myeclipse的最新版本及相應的eclipse開發平臺版本
2.2 準備Mondrian資源:
從http://sourceforge.net/projects/mondrian/下載Mondrian的最新版本(目前版本為3.0,大約有50M+大小)。
2.3 創建項目
啟動eclipse。
在eclipse中新創建一個web項目,名為Tezz。注意需要加入JSTL支持。
具體步驟如下:
2.3.1 打開新建web項目對話框
一個新項目Tezz的文件結構如下:
2.4 添加必須的文件
將下載的壓縮包進行解壓。完成后,進入文件夾可以看到如下目錄結構。雙擊進入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的功能。
2.5 配置web.xml
用eclipse打開我們在上面解壓的布署項目的WEB-INF/web.xml文件
過濾器(filter)
復制如下所示的xml代碼到我們測試項目Tezz的web.xml文件中。
作用:這個過濾器在訪問/testpage.jsp前被調用。它被設計成jpivot的前端控制器,用于判斷并將用戶的請求發送到某個頁面。
注:在實際項目中可以使用您自己定義的servlet或使用其他技術來替代它以提供更多的功能
- <filter>
- <filter-name>JPivotController</filter-name>
- <filter-class>com.tonbeller.wcf.controller.RequestFilter</filter-class>
- <init-param>
- <param-name>indexJSP</param-name>
- <param-value>/index.html</param-value>
- <description>如果這是一個新的會話,則轉到此頁面</description>
- </init-param>
- <init-param>
- <param-name>errorJSP</param-name>
- <param-value>/error.jsp</param-value>
- <description>出錯時顯示的頁面</description>
- </init-param>
- <init-param>
- <param-name>busyJSP</param-name>
- <param-value>/busy.jsp</param-value>
- <description>這個頁面用于當用戶點擊一個查詢時,在這個查詢還未將結果還回給用戶時所顯示的界面</description>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>JPivotController</filter-name>
- <url-pattern>/testpage.jsp</url-pattern>
- </filter-mapping>
- <listener>
- <listener-class>mondrian.web.taglib.Listener</listener-class>
- </listener>
- <!– 資源初始化-->
- <listener>
- <listener-class>com.tonbeller.tbutils.res.ResourcesFactoryContextListener</listener-class>
- </listener>
- <servlet>
- <servlet-name>Print</servlet-name>
- <display-name>Print</display-name>
- <description>Default configuration created for servlet.</description>
- <servlet-class>com.tonbeller.jpivot.print.PrintServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>Print</servlet-name>
- <url-pattern>/Print</url-pattern>
- </servlet-mapping>
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文件中。
- <servlet>
- <servlet-name>MDXQueryServlet</servlet-name>
- <servlet-class>mondrian.web.servlet.MDXQueryServlet</servlet-class>
- <init-param>
- <param-name>connectString</param-name>
- <param-value>@mondrian.webapp.connectString@</param-value>
- </init-param>
- </servlet>
- <servlet-mapping>
- <servlet-name>MDXQueryServlet</servlet-name>
- <url-pattern>/mdxquery</url-pattern>
- </servlet-mapping>
- <!-- jfreechart provided servlet -->
- <servlet>
- <servlet-name>DisplayChart</servlet-name>
- <servlet-class>org.jfree.chart.servlet.DisplayChart</servlet-class>
- </servlet>
- <!-- jfreechart provided servlet -->
- <servlet>
- <servlet-name>GetChart</servlet-name>
- <display-name>GetChart</display-name>
- <description>Default configuration created for servlet.</description>
- <servlet-class>com.tonbeller.jpivot.chart.GetChart</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>DisplayChart</servlet-name>
- <url-pattern>/DisplayChart</url-pattern>
- </servlet-mapping>
- <servlet-mapping>
- <servlet-name>GetChart</servlet-name>
- <url-pattern>/GetChart</url-pattern>
- </servlet-mapping>
最后添加以下標簽庫到我們的web.xml項目中即可
- <taglib>
- <taglib-uri>http://www.tonbeller.com/wcf</taglib-uri>
- <taglib-location>/WEB-INF/wcf/wcf-tags.tld</taglib-location>
- </taglib>
- <taglib>
- <taglib-uri>http://www.tonbeller.com/jpivot</taglib-uri>
- <taglib-location>/WEB-INF/jpivot/jpivot-tags.tld</taglib-location>
- </taglib>
接下來我們將要創建本例子所要用到的表格及數據。
2.6 準備測試用表
本例使用的表結構如下所示:
Sale是事實表,它有兩個維:客戶(customer)維和由兩個表組成的產品(Product)維。
表格的創建很簡單,您只需要將下面的sql語句導入數據庫即可
2.6.1 使用以下sql語句創建表
- /**銷售表*/
- 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)
- )
2.6.2 使用以下sql語句導入數據
- 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)
2.7 建立模式(schema)文件
一個模式定義了一個多維數據庫. 它包含一個邏輯模型(logical model)、一組數據立方(consisting of cubes)、層次(hierarchies)、和成員(members), 并映射到物理模型(關系數據庫)上。
簡單的說,配置一個模式就是配置一個關系數據結構到多維數據結構的映射。
注:關于mondrian的模式及模式的配置,您可以通過閱讀mondrian的基本模式.pptx來了解。這里我們只對其進行了簡單介紹。
2.7.1 創建模式文件:
模式文件的創建很簡單。首先在WEB-INF下新建一個queries的文件夾,然后在該文件夾下創建一個名為tezz.xml的文件。再按下面的步驟將xml元素添加入即可。
2.7.2 配置模式文件:
2.7.2.1 添加數據立方Sales:
2.7.2.2 添加數據立方Sales的維:
添加產品維(因為產品維由兩個表連接而成,因此比客戶維復雜些):
添加度量(共有三個度量:數量、平均單價和總銷售額):
最后生成的tezz.xml文件內容如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <Schema name="tezz">
- <Cube name="Sales">
- <!-- 事實表(fact table) -->
- <Table name="sale" />
- <!-- 客戶維 -->
- <Dimension name="客戶性別" foreignKey="cusId">
- <Hierarchy hasAll="true" allMemberName="所有性別" primaryKey="cusId">
- <Table name="Customer"></Table>
- <Level name="gender" column="gender"></Level>
- </Hierarchy>
- </Dimension>
- <!-- 產品類別維 -->
- <Dimension name="產品類別" foreignKey="proId">
- <Hierarchy hasAll="true" allMemberName="所有產品" 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="數量" column="number" aggregator="sum" datatype="Numeric" />
- <Measure name="總銷售額" aggregator="sum" formatString="¥#,##0.00">
- <!-- unitPrice*number所得值的列 -->
- <MeasureExpression>
- <SQL dialect="generic">(unitPrice*number)</SQL>
- </MeasureExpression>
- </Measure>
- <CalculatedMember name="平均單價" dimension="Measures">
- <Formula>[Measures].[總銷售額] / [Measures].[數量]</Formula>
- <CalculatedMemberProperty name="FORMAT_STRING" value="¥#,##0.00" />
- </CalculatedMember>
- </Cube>
- </Schema>
2.8 編寫MDX查詢語句
在模式文件定義完成之后,我們就可以根據它來編寫相應MDX查詢語句了。
本例所用的MDX語句如下:
2.9 創建查詢文件
現在我們將創建一個jsp文件,該jsp使用jpivot的mondrianQuery標簽來完成查詢。
該文件最后將被testpage.jsp使用。
在/WEB-INF/queries文件夾下面創建一名為tezz的jsp文件。該jsp包含如下內容:
2.10 布署項目
至此我們已經全部配置完成,文件結構如下:
布署項目,啟動Tomcat,在瀏覽器上輸入http://localhost:8080/Tezz/testpage.jsp?query=tezz即可看到如下結果:
注:testpage.jsp?query=tezz,這里的tezz即剛我們創建的用于查詢jsp文件名稱
3. testpage.jsp的流程
testpage.jsp文件用于發出查詢及將結果轉換成html格式。它使用一組jsp標簽來完成這些復雜的工作。
在本教程的最后一章里,我們對testpage.jsp的流程及用到的主要標簽進行簡單介紹。
3.1 wcf:include標簽:
3.2 jp:table標簽:
<jp:table id="table01" query="#{query01}"/>
jp:table根據query01中保存的結果(領域數據)準備顯示OLAP表格所需的數據(顯示數據)
<wcf:render ref="table01" xslUri="/WEB-INF/jpivot/table/mdxtable.xsl"/>
根據table01的結果,使用mdxtable.xsl中的配置,渲染出OLAP表格。
3.3 其他jp、wcf標簽
同樣,其他jp標簽,如<jp:chart id=“chart01“ ---/>等標簽準備待渲染的數據,再由相應的<wcf:render ref=“chart01” ---/>標簽將它們渲染成html格式。
這樣,用戶將在瀏覽器上看到最終的結果。
至此,一個完整的mondrian查詢結束。
posted @ 2016-02-06 18:18 gdufo| 編輯 收藏