1. 程式人生 > >OLAP了解與OLAP引擎——Mondrian入門(一)

OLAP了解與OLAP引擎——Mondrian入門(一)

本質 ear 發送 這一 proc pattern 接下來 oracle 簡單

一、 OLAP的基本概念

OLAP(On-Line Analysis Processing)在線分析處理是一種共享多維信息的快速分析技術;OLAP利用多維數據庫技術使用戶從不同角度觀察數據;OLAP用於支持復雜的分析操作,側重於對管理人員的決策支持,可以滿足分析人員快速、靈活地進行大數據復量的復雜查詢的要求,並且以一種直觀、易懂的形式呈現查詢結果,輔助決策。

二、 OLAP的基本內容

(1)變量(度量)

變量是數據度量的指標,是數據的實際意義,即描述數據“是什麽”。像示例中的人數。

(2)維度

維度是描述與業務主題相關的一組屬性,單個屬性或屬性集合可以構成一個維。如示例中的學歷、民族、性別等都是維度。

(3)維的層次

一個維往往可以具有多個層次,例如時間維度分為年、季度、月和日等層次,地區維可以是國家、地區、省、市等層次。這裏的層次表示數據細化程度,對應概念分層。後面介紹的上鉆操作就是由低層概念映射到高層概念。概念分層可除根據概念的全序和偏序關系確定外,還可以通過對數據進行離散化和分組實現。

(4)維的成員

若維是多層次的,則不同的層次的取值構成一個維成員。部分維層次同樣可以構成維成員,例如“某年某季度”、“某季某月”等都可以是時間維的成員。

(5)多維數組

多維數組用維和度量的組合表示。一個多維數組可以表示為(維1,維2,……,維n,變量),例如(部門,職系、民族、性別,人數)組成一個多維數組。

(6)數據單元(單元格)

多維數組的取值。當多維數組中每個維都有確定的取值時,就唯一確定一個變量的值。數據單元可以表示為(維1成員,維2成員,……,維N成員,變量的值),例如(人事教育部,技能,回族,男,1人)表示一個數據單元,表示人事教育部職系是技能的回族男性有1人。

(7)事實

事實是不同維度在某一取值下的度量,例如上述人事教育部職系是技能的回族男性有1人就表示在部門、職系、民族、性別四個維度上企業人數的事實度量,並且在為人數事實中包含部門維度人事教育部這一個維度層次,如果將人數事實的所有維度考慮在內,就構成有關人數的多維分析立方體。

三、 OLAP的特點

電子數據表與OLAP相比,不具備OLAP的多維性、層次、維度計算以及結構與視圖分離等特點。

1.快速。終端用戶對於系統的快速響應有很高的要求。調查表明如果用戶在30秒內得不到回應,就會變得不耐煩。因此OLAP平臺彩用了多種技術提高響應速度,例如專門的數據存儲格式、大量的預處理和特殊的硬件設計等,通過減小在線分析處理的動態計算,事先存儲OLAP所需粒度的數據等主要手段來獲得OLAP響應速度的提高,盡管如此,查詢反應慢仍然是OLAP產品中經常被提及的問題。

2.可分析。用戶可以應用OLAP平臺分析數據,也可以使用其他外部分析工具,例如電子數據表,這些分析工具基本上都以直觀的方式為用戶提供了分析功能。

3.共享。由於人們認為OLAP是只讀的,僅需要簡單的安全管理,導致目前許多OLAP產品在安全共享方面還存在許多問題。因此當多個用戶訪問OLAP服務器時,系統就在適當的粒度上加鎖。

4.多維。維是OLAP的核心概念,多維性是OLAP的關鍵屬性,這與數據倉庫的多維數據組織正好相互補充。為了使用戶能夠從多個維度、多個數據粒度查看數據,了解數據蘊含的信息,系統需要提供對數據的多維分析功能,包括切片、旋轉和鉆取等多種操作

四、 OLAP的操作

OLAP比較常用的操作包括對多維數據的切片與切塊、上鉆(drill-up)與下鉆(drill-down)以下旋轉(rotate)等。此外,OLAP還能對多維數據進行深加工。OALP的這些操作使用戶能夠從多個視角觀察數據,並以圖形、報表等多種形式展示,從而獲取隱藏在數據中的信息。

(1)切片與切塊。

選定多維數組的一個維成員做數據分割的操作稱為該維上的一個切片。通常把多維數組中選定一個二維子集的操作視為切片,假設選定的維i上的某個維成員Vi,則此多維數組子集可以定義為(維V1……,維Vi,維N,變量)。當某維只取一個維成員時,便得到一個切片,而切塊則是某一維取值範圍下的多個切片的疊合。通過對數據立方體的切片或切塊分割,可以從不同的視角得到各種數據。

(2)鉆取

鉆取包括上鉆和下鉆。爭取能夠幫助用戶獲得更多的細節性數據,逐層的分析問題的所在和原因。

  • § 上鉆又稱為上卷(roll-up)。上鉆操作是指通過一個維的概念分層向上攀升或者通過維歸約在數據立方體上進行數據匯總。例如在上面的示例中,可以按學歷匯總數據,如把各種學歷的都歸約為所有學歷,便可以得到沿學歷維上鉆的數據匯總。
  • § 下鉆是上鉆的逆操作,通過對某一匯總數據進行維層次的細分(沿維的概念分層向下)分析數據。下鉆使用用戶對數據能夠獲得更深入的了解,更容易發現問題本質,從而做出正確的決策。
  • § 鉆取使用戶不會再被海量的數據搞得暈頭轉向:上鉆讓用戶站在更高層次觀察數據,下鉆則可以細化到用戶所判決的詳細數據。鉆取的嘗試與維度與維所劃分的層次相對應,根據用戶關心的數據粒度合理劃分。

(3)旋轉

旋轉又稱轉軸,是一種視圖操作,通過旋轉變換一個報告或頁面顯示的維度方向,在表格中重新安排維的位置,例如行列轉換。這種對立方體的重定位可以得到不同視角的信息。

(4)其他OLAP操作

除以上常用多維操作外,還有其他多維操作。

  • § 鉆過(drill-across)。鉆過操作涉及多個事實表的查詢並把結果合並為單個數據集,一個典型的例子就是預測數據與當前數據的結合:通常預測數據與當前數據存在於不同的表中,當用戶比較預測銷售與當月銷售時,需要跨多個事實表查詢。
  • § 鉆透(drill-through)。鉆透使用關系SQL,查詢數據立方體的底層,一直到後羰的關系表。

五、 OLAP的分類

OLAP的分類,如下圖所示

按處理方式分類

  • § Server OLAP:絕大多數的OLAP系統都屬於此類,Server OLAP在服務端的數據庫上建立多維數據立方體,由服務端提供多維分析,並把最終結果呈現給用戶
  • § Client OLAP:所相關立方體數據下載一本地,由本地為用戶提供多維分析,從而保證在網絡故障時仍然能正常工作。

按存儲方式分類

  • § ROLAPROLAP使用關系數據庫或擴充關系數據庫(XRDBMS)存儲管理數據倉庫,以關系表存儲多維數據,有較強的可伸縮性。其中維數據存儲在維表中,而事實數據和維ID則存儲在事實表中,維表和事實表通過主外鍵關聯。
  • § MOLAP。MOLAP支持數據的多維視圖,采用多維數據組存儲數據,它把維映射到多維數組的下標或下標的範圍,而事實數據存儲在數組單元中,從而實現了多維視圖到數組的映射,形成了立方體的結構。大容量的數據使立方體稀疏化,此時需要稀疏矩陣壓縮技術處理,由於MOLAP是從物理上實現,故又稱為物理OLAP(Physical OLAP)。
  • § DOLAPDOLAP是屬於單層架構,它是基於桌面的客戶端OLAP,主要特點是由服務器生成請求數據相關的立方體並下載到本地,由本地提供數據結構與報表格式重組,為用戶提供多維分析,此時無需任何的網絡連接,靈活的存儲方式方便了移動用戶的需求,但支持數據有限,使用範圍有限。

一、 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. <taglib>
  6. <taglib-uri>http://www.tonbeller.com/jpivot</taglib-uri>
  7. <taglib-location>/WEB-INF/jpivot/jpivot-tags.tld</taglib-location>
  8. </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文件中盡量避免出現中文。

OLAP了解與OLAP引擎——Mondrian入門(一)