2008年3月26日

          Mondrian是一個開放源代碼的Rolap服務器,使用java開發(fā)的。它實現(xiàn)了xmla和jolap規(guī)范,而且自定義了一種使用mdx語言的客戶端接口。Mondrian是olap服務器,而不是數(shù)據(jù)倉庫服務器,因此Mondrian的元數(shù)據(jù)主要包括olap建模的元數(shù)據(jù),不包括從外部數(shù)據(jù)源到數(shù)據(jù)庫轉換的元數(shù)據(jù)。也就是說Mondria的元數(shù)據(jù)僅僅包括了多維邏輯模型,從關系型數(shù)據(jù)庫到多維邏輯模型的映射,存取權限等信息。在功能上,Mondrian支持共享維和成員計算,支持星型模型和雪花模型的功能。
          Mondrian中使用物理的xml文件存儲元數(shù)據(jù),它的設計者規(guī)定了xml文件的格式。下面簡單介紹一下它是如何存儲元數(shù)據(jù)的。

          Element Description
          根元素
          <Schema> Collection of Cubes, Virtual cubes, Shared dimensions, and Roles.
          邏輯元素
          <Cube> A collection of dimensions and measures, all centered on a fact table.
          <VirtualCube> A cube defined by combining the dimensions and measures of one or more cubes.
          <Dimension>
          <DimensionUsage> Usage of a shared dimension by a cube.
          <Hierarchy>
          <Level>
          <Property>
          <Measure>
          物理元素
          <Table> Fact- or dimension table.
          <View> Defines a 'table' using a SQL query, which can have different variants for different underlying databases.
          <Join> Defines a 'table' by joining a set of queries.
          存取控制
          <Role> An access-control profile.
          <SchemaGrant> A set of rights to a schema.
          <CubeGrant> A set of rights to a cube.
          <HierarchyGrant> A set of rights to a hierarchy and levels within that hierarchy.
          <MemberGrant> A set of rights to a member and its children.
          其他
          <Parameter>
          <Table>
          <Table>



          一個模式定義一個多維數(shù)據(jù)庫,它包括一個邏輯模型,由立方體,層次,成員和邏輯模型到物理模型的映射構成。一個邏輯模型由可以用MDX語言來查詢。Mondrain的模型由xml文件來描述?,F(xiàn)在創(chuàng)建模式的唯一途徑是用文本編輯a器編輯xml文件。Xml的語法不是太復雜,因此沒有想象中的那么難。目前正在開發(fā)一個圖形界面的程序來創(chuàng)建和修改模式。
          一個模式最重要的組成部分是立方體,度量和維:在一個主題域中立方體是維和度量的集合。一個度量是一個可測量的數(shù)值,比如產(chǎn)品銷售的數(shù)量或者詳細清單的價格
          一個維是一個屬性或者是屬性的集合, 通過維你可以將度量劃分到字類中。比如:你希望將銷售產(chǎn)品按顏色,顧客性別,售出的商店分為八個部分,那么顏色,性別,商店都是維。

          下面是一個簡單的模型定義的例子:
          <Schema>
          <Cube name="Sales">
          <Table name="sales_fact_1997"/>
          <Dimension name="Gender" foreignKey="customer_id">
          <Hierarchy hasAll="true" allMemberName="All Genders" primaryKey="customer_id">
          <Table name="customer"/>
          <Level name="Gender" column="gender" uniqueMembers="true"/>
          </Hierarchy>
          </Dimension>
          <Dimension name="Time" foreignKey="time_id">
          <Hierarchy hasAll="false" primaryKey="time_id">
          <Table name="time_by_day"/>
          <Level name="Year" column="the_year" type="Numeric"
          uniqueMembers="true"/>
          <Level name="Quarter" column="quarter"
          uniqueMembers="false"/>
          <Level name="Month" column="month_of_year" type="Numeric"
          uniqueMembers="false"/>
          </Hierarchy>
          </Dimension>
          <Measure name="Unit Sales" column="unit_sales"
          aggregator="sum" formatString="#,###"/>
          <Measure name="Store Sales" column="store_sales"
          aggregator="sum" formatString="#,###.##"/>
          </Cube>
          </Schema>

          這個模型包含了一個銷售cube,這個cube有兩個維,時間和性別維;兩個度量,銷售數(shù)量和銷售總額。
          我們可以在這個模型上寫一個 MDX 查詢:
          select {[Measures].[Unit Sales], [Measures].[Store Sales]} on columns,
          {[Time].[1997].[Q1].descendants} on rows
          from [Sales]
          where [Gender].[F]
          這 個查詢涉及到了銷售立方體, 每一個維 [Measures], [Time], [Gender], 這些維的多個成員. 結果如下:
          [Time] [Measures].[Unit Sales] [Measures].[Store Sales]
          [1997].[Q1] 0 0
          [1997].[Q1].[Jan] 0 0
          [1997].[Q1].[Feb] 0 0
          [1997].[Q1].[Mar] 0 0

          下面詳細地介紹一下模式定義:
          一個立方體是一個或者多個維和度量的集合,通常是一個事實表,這里是 ‘sales_fact_1997". 事實表保存了需要計算的列和包含維的參考表.
          <Cube name="Sales">
          <Table name="sales_fact_1997"/>
          ...
          </Cube>
          這里用 <Table> 元素定義事實表. 如果事實表 不在默認的模式中, 你可以用"schema"屬性指定一個明確地模式,例如:
          <Table schema="foodmart" name="sales_fact_1997"/>
          你也可以利用 <View> 和 <Join> 結構來創(chuàng)建更復雜的sql .
          度量
          銷售立方體定義了兩個維 "Unit Sales" 和 "Store Sales".
          <Measure name="Unit Sales" column="unit_sales"
          aggregator="sum" formatString="#,###"/>
          <Measure name="Store Sales" column="store_sales"
          aggregator="sum" formatString="#,###.00"/>
          每個度量有一個名字,對應事實表中的一列, 采用一個聚集函數(shù) (usually "sum").
          一個可選的格式字符串指定了值如何被打印. 這里我們選擇銷售數(shù)量不帶小數(shù)的輸出(因為銷售數(shù)量是整數(shù)) ,銷售總額帶2位小數(shù) . 符號',' 和 '.' 是對地區(qū)敏感的, 因此如果是在意大利運行, 銷售總額可能會出現(xiàn) "48.123,45". 你可以用 advanced format strings來實現(xiàn)更嚴格的效果.度量值不是從列中來的,而是從立方體的單元中來的

          性別維由單一的層次組成,僅有一層。
          <Dimension name="Gender" foreignKey="customer_id">
          <Hierarchy hasAll="true" primaryKey="customer_id">
          <Table name="customer"/>
          <Level name="Gender" column="gender" uniqueMembers="true"/>
          </Hierarchy>
          </Dimension>
          對于任意給定的銷售, 性別維是指購買改產(chǎn)品的客戶的性別. 它通過連接事實表"sales_fact_1997.customer_id"和維表"customer.customer_id"
          來表示 。"gender" 包括兩個值, 'F' 和 'M', 因此性別維包含的成員: [Gender].[F] and [Gender].[M]. 因為 hasAll="true", 系統(tǒng)產(chǎn)生一個特別的 'all' 層, 僅包括一個成員 [All Genders].
          一個維可以包含多個層次:
          <Dimension name="Time" foreignKey="time_id">
          <Hierarchy hasAll="false" primaryKey="time_id">
          <Table name="time_by_day"/>
          <Level name="Year" column="the_year" type="Numeric"
          uniqueMembers="true"/>
          <Level name="Quarter" column="quarter"
          uniqueMembers="false"/>
          <Level name="Month" column="month_of_year" type="Numeric"
          uniqueMembers="false"/>
          </Hierarchy>
          <Hierarchy name="Time Weekly" hasAll="false" primaryKey="time_id">
          <Table name="time_by_week"/>
          <Level name="Year" column="the_year" type="Numeric"
          uniqueMembers="true"/>
          <Level name="Week" column="week"
          uniqueMembers="false"/>
          <Level name="Day" column="day_of_week" type="String"
          uniqueMembers="false"/>
          </Hierarchy>
          </Dimension>
          第一個層次沒有指定名稱.缺省的情況下,一個層次擁有和它的維相同的名稱。,因此第一個層次成為"Time".這些層次沒有太多的共同之處,他們甚至沒有相同的表,除非它們連接了實施表中的同一列"time_id"。在一個維上存在兩個層次的原因是這樣對最終用戶是有用的. 如果一個維上存在兩個層次, MDX會強制不允許在一個查詢中同時用到他們.
          A dimension can live in the fact table:
          <Cube name="Sales">
          <Table name="sales_fact_1997"/>
          ...
          <Dimension name="Payment method">
          <Hierarchy hasAll="true">
          <Level name="Payment method" column="payment_method" uniqueMembers="true"/>
          </Hierarchy>
          </Dimension>
          </Cube>
          每個維包含有多層組成的一個層次,

          大多數(shù)維都是僅有一個層次,但有時候一個維有多個層次。比如:你可能希望在時間維上從天聚集到月,季度和年;或者從天聚集到周和年。這兩種層次都是從天到年,但是聚集的路徑不同。大多數(shù)層次有全成員,全成員包括層次的所有成員,因此能夠代表他們的總合。它通常命名為'All something',比如:'All stores'.




          星型模式和雪花模式
          mondrian支持星型模式和雪花模式。下面介紹一下雪花模式的建模,它需要用到操作符 <Join>.比如:
          <Cube name="Sales">
          ...
          <Dimension name="Product" foreignKey="product_id">
          <Hierarchy hasAll="true" primaryKey="product_id" primaryKeyTable="product">
          <Join leftKey="product_class_id" rightAlias="product_class" rightKey="product_class_id">
          <Table name="product"/>
          <Join leftKey="product_type_id" rightKey="product_type_id">
          <Table name="product_class"/>
          <Table name="product_type"/>
          </Join>
          </Join>
          ...
          </Hierarchy>
          </Dimension>
          </Cube>
          這里定義一個 "Product" 維 由三個表構成. 事實表連接 表"product" (通過外鍵 "product_id"),表"product"連接表"product_class" (通過外鍵 "product_class_id"),表"product_class"連接表 "product_type" (通過外鍵 "product_type_id"). 我們利用 <Join> 元素的循環(huán)嵌套, <Join>帶有兩個操作對象; 操作對象可能是表,連接或者查詢 。
          按照操作對象行的數(shù)目來安排次序,表 "product" 的行數(shù)最大, 因此它首先出現(xiàn)連接事實表;然后是表 "product_class"和 "product_type",在雪花的末端擁有的行數(shù)最小.
          注意外部元素 <Join>有一個屬性 rightAlias. 這是必要的,因為join 的右邊(是內部元素 <Join> ) 有可能是許多表組成的.這種情況下不需要屬性leftAlias,因為列 leftKey 很明確的來自表 "product".

          共享維
          當為一個連接生成SQL的時候, mondrian 需要知道連接哪一個列. 如果一正在連接一個多表連接, 你需要告訴它連接這些表里的哪一個表,哪一個列.
          因為共享維不屬于一個cube,你必須給它們一個明確的表 (或者數(shù)據(jù)源). 當你在一個特別的cube里用他們的時候, 你要指定外鍵 foreign key. 下面的例子顯示了 Store Type 維被 連接到 Sales cube ,用了外鍵 sales_fact_1997.store_id, 并且被連接到Warehouse cube ,用了外鍵 warehouse.warehouse_store_id :
          <Dimension name="Store Type">
          <Hierarchy hasAll="true" primaryKey="store_id">
          <Table name="store"/>
          <Level name="Store Type" column="store_type" uniqueMembers="true"/>
          </Hierarchy>
          </Dimension>

          <Cube name="Sales">
          <Table name="sales_fact_1997"/>
          ...
          <DimensionUsage name="Store Type" source="Store Type" foreignKey="store_id"/>
          </Cube>

          <Cube name="Warehouse">
          <Table name="warehouse"/>
          ...
          <DimensionUsage name="Store Type" source="Store Type" foreignKey="warehouse_store_id"/>
          </Cube>




          虛擬 cubes
          父子層次
          一個使用方便的層次 有一個嚴格的層的集合, 成員與層緊密的聯(lián)系.比如,在 Product 層次中, 任何產(chǎn)品名稱層的成員在商標層上都有一個父親 ,商標層上的成員在產(chǎn)品子目錄層也都有一個父親. 這種結構對于現(xiàn)實世界中的數(shù)據(jù)有時候太嚴格了.
          一個父子層次只有一層 (不計算 'all' 層), 但是任何成員可以在同一層上有父親成員. 一個典型的例子是Employees 層次:
          <Dimension name="Employees" foreignKey="employee_id">
          <Hierarchy hasAll="true" allMemberName="All Employees" primaryKey="employee_id">
          <Table name="employee"/>
          <Level name="Employee Id" uniqueMembers="true" type="Numeric"
          column="employee_id" nameColumn="full_name"
          parentColumn="supervisor_id" nullParentValue="0">
          <Property name="Marital Status" column="marital_status"/>
          <Property name="Position Title" column="position_title"/>
          <Property name="Gender" column="gender"/>
          <Property name="Salary" column="salary"/>
          <Property name="Education Level" column="education_level"/>
          <Property name="Management Role" column="management_role"/>
          </Level>
          </Hierarchy>
          </Dimension>
          這里parentColumn 和nullParentValue是重要的屬性:
          屬性parentColumn 是一個成員連接到它父親成員的列名。在這種情況下, 它是指向雇員經(jīng)理的外鍵。元素<Level>的子元素 <ParentExpression> 是與屬性 parentColumn 有相同作用的,但是元素允許定義任意的SQL表達式, 就像元素 <Expression>. 屬性 parentColumn (或者 元素<ParentExpression>) 是維一向Mondrian指出 層次有父子結構的。
          屬性 nullParentValue 是指明成員沒有父成員的值 。 缺省情況下 nullParentValue="null", 但是因為許多數(shù)據(jù)庫不支持null, 建模時 用其他值來代替空值,0和-1.

          物理結構
          member reade
          member reader 是訪問成員的方法. 層次通常以維表為基礎建立的 , 因此要用sql來構造.但是甚至你的數(shù)據(jù)沒有存在于 RDBMS, 你可以通過一個 Java 類來訪問層次。(自定義 member reader)
          Here are a couple of examples:
          DateSource (to be written)生成一個時間層次. 按常規(guī),數(shù)據(jù)倉庫工具生成一個表 ,每天包含一行。但是問題是這個表需要裝載,并且隨著時間的變化能夠添加更多的行。 DateSource 在內存中按照要求生成日期成員.
          FileSystemSource (to be written) 按照目錄和文件的層次描述文件系統(tǒng)。 Like the time hierarchy created by DateSource, this is a virtual hierarchy: the member for a particular file is only created when, and if, that file's parent directory is expanded.
          ExpressionMemberReader (to be written) 創(chuàng)建了一個基于表達式的層次。
          自定義member reader 必須實現(xiàn)接口 mondrian.rolap.MemberSource. 如果你需要實現(xiàn)一個更大的成員操作集合, 需要實現(xiàn)接口 interface mondrian.rolap.MemberReader; 否則, Mondrian在 mondrian.rolap.CacheMemberReader中封裝 你的 reader類.你的 member reader 必須有一個公共的構造函數(shù),這個構造函數(shù)擁有參數(shù)(Hierarchy,Properties),拋出未檢查的錯誤.
          Member readers 用 元素<Hierarchy> 的屬性memberReaderClass來聲明; 任何 <Parameter> 子元素通過屬性構造函數(shù)來傳遞.
          這是一個例子:
          <Dimension name="Has bought dairy">
          <Hierarchy hasAll="true" memberReaderClass="mondrian.rolap.HasBoughtDairySource">
          <Level name="Has bought dairy" uniqueMembers="true"/>
          <Parameter name="expression" value="not used"/>
          </Hierarchy>
          </Dimension>
          Cell readers
          <Measure name="name" cellReaderClass="com.foo.MyCellReader">
          類 "com.foo.MyCellReader" 實現(xiàn)了接口interface mondrian.olap.CellReader.


          存取控制
          可以定義存取控制的屬性(角色), 作為模式的一部分, 并且可以在建立連接的時候設置角色。
          定義角色
          角色可以通過 元素<Role>來設置 , 它是元素<Schema> 的直接的子元素.
          下面是一個關于角色的例子:
          <Role name="California manager">
          <SchemaGrant access="none">
          <CubeGrant cube="Sales" access="all">
          <HierarchyGrant hierarchy="[Store]" access="custom" topLevel="[Store].[Store Country]">
          <MemberGrant member="[Store].[USA].[CA]" access="all"/>
          <MemberGrant member="[Store].[USA].[CA].[Los Angeles]" access="none"/>
          </HierarchyGrant>
          <HierarchyGrant hierarchy="[Customers]" access="custom" topLevel="[Customers].[State Province]" bottomLevel="[Customers].[City]">
          <MemberGrant member="[Customers].[USA].[CA]" access="all"/>
          <MemberGrant member="[Customers].[USA].[CA].[Los Angeles]" access="none"/>
          </HierarchyGrant>
          <HierarchyGrant hierarchy="[Gender]" access="none"/>
          </CubeGrant>
          </SchemaGrant>
          </Role>
          元素 <SchemaGrant> 定義了模式中缺省的對象方問權限. 訪問屬性可以是 "all" 或者 "none"; 這個屬性可以被具體的權限對象繼承. 在這個例子中, 因為 access="none", 用戶只能瀏覽"Sales" 立方體, 這里明確的賦予了這個權限.
          元素 <CubeGrant> 定義了立方體的訪問權限. 就像 <SchemaGrant>, 屬性access 可以是"all" 或者 "none", 并且能夠被cube中具體的子對象繼承.
          元素 <HierarchyGrant>定義了層次的訪問權限. 屬性access 可以是"all", 意思是所有的members都是可見的; "none",意思是 hierarchy的存在對用戶是隱藏的; "custom", 你可以利用屬性 topLevel 定義可見的最高層 (阻止用戶 進行上卷操作, 比如瀏覽稅收 上卷到 Store Country 層); 或者用屬性 bottomLevel 定義可見的最底層 (這里阻止用戶查看顧客個人的細節(jié)數(shù)據(jù));或者控制用戶查看哪一個成員集合,通過嵌套定義元素 <MemberGrant>.
          你也可以只定義元素 <MemberGrant> ,如果模式的<HierarchyGrant> 有屬性access="custom". Member grants 賦予 (或者取消) 訪問給定的成員, 以及它的所有子成員.
          posted @ 2008-03-26 22:30 edsonjava 閱讀(926) | 評論 (0)編輯 收藏
           
          改了不少JPivot/mondrian代碼,還修正了jpivot一個bug。

          對JPivot的jfreechart和drillthrough顯示做了增強,終于可以拿出去給人用了。

          先說說性能問題: 先是找了一臺閑置的IBM X445 PC Server,4×2GHZ CPU,8G內存,2×146G硬盤,操作系統(tǒng) windows 2000 , 開啟AWE 3G參數(shù)。然后裝Oracle 10g,數(shù)據(jù)倉庫模式,使用了4G AWE內存共約4.5GB內存。再建成一張1600萬用戶數(shù)據(jù)寬表,寬表一律使用bitmap索引,還有其他20個左右維表。 然后就簡單了,寫mondrian Cube,配JPivot。 最后搞下來的結果是:基本上mondrian 每次做group by 操作最長不超過30秒,一般在20秒左右。用戶基本可以接受。問了使用NCR的朋友,說NCR使用自己的數(shù)據(jù)庫,也基本是這樣的一個性能。 PS:偷偷問一聲,在這基礎上,性能還能改進否?

           

          再說說方向問題: 我們現(xiàn)在使用2個OLAP,一個是jpivot + mondrian ,屬于ROLAP;另一個是BO intelligence + essbase,屬于MOLAP。目前的感覺是,由于DB性能強悍,導致ROLAP和MOLAP在性能上相差不大。同時ROLAP可以直接和報表系統(tǒng)共用同一張表。而MOLAP則需要使用工具來打CUBE做數(shù)據(jù)轉換,這樣在開發(fā)和維護工作量上,MOLAP比ROLAP大。 另外往往業(yè)務部門分析到最后,就是要看明細數(shù)據(jù)了,這個時候MOLAP的前端工具往往不能做好支持。而jpivot則無此問題。 綜上所述,我目前好像還沒看到必須用MOLAP的理由,聽說華為原來用M$ 的OLAP,后來好像支持不住了,就直接用回了BO 報表,呵呵。

           

          JPivot的問題: 操作太復雜,必須對OLAP的概念有清晰的了解,普通用戶無法使用。與mondrian 集成不夠緊密。mondrian不提供數(shù)據(jù)鉆取功能,該功能是jpivot自己做的,所以會導致數(shù)據(jù)類型格式丟失。鉆取詳細數(shù)據(jù)量無限制,導致內存溢出。界面比較難看,操作方式非主流使用jpivot自己的mvc框架,不易其他框架集成 總體來說,jpivot目前已經(jīng)不是一個玩具了,完全可以用于企業(yè)級的操作,而且定位在高端業(yè)務分析人員。


          拿出來開源比較困難,一方面jpivot在不停升級,另一方面我在修改的時候不顧一切,在jpivot中亂引用了mondrian代碼,還把mondrian部分無用代碼全刪了。這樣,我就在這個帖里把能共享部分都在這里帖出來。 首先是我優(yōu)化后的界面。 1.圖標用了pentaho里面的圖標。 2.jpivot里面其實支持3D餅圖,只是選項未開,我先將jfreechart升級成1.0.2,又對餅圖、線圖等做了美觀。 3.drillthrough是jpivot相對其他olap產(chǎn)品的殺手級功能,但是有不少細節(jié)未完善。我基本都一一補上。 在界面上可以看出,我添加了一個CSV導出功能(改了WCF庫),同時限制最大導出20萬行記錄(改了jpivot)。界面上顯示的“訪問次數(shù)”是measure的名字,實際上應該顯示“訪問時間”,該問題暫時無解。另外修正了一下numberformat、dateformat不正確的一些問題。 4.excel導出時,格式很難看,但是由于excel本身只支持256色,無法顯示web上的底色,所以我修改了只顯示藍色的border,底色一律為白。 附件中rar里面是web的CSS文件、Excel的生成文件和jpivot的圖表生成部分代碼,感興趣的朋友各取所需吧


          另外還把jpviot完全整合到我自己的系統(tǒng)中去了,呵呵。 可以在系統(tǒng)web界面上編寫Cube和MDX定義,Cube和MDX為一對多關系。Cube通過xsd來做校驗。開發(fā)Cube和MDX的時候可以隨時做預覽。 然后再把一個MDX在界面發(fā)布成一個單獨的OLAP分析。 下一步的目標是將數(shù)據(jù)權限與jpivot做整合,由于Cube的xml是由系統(tǒng)自動生成的,所以mondrian的role配置也可以由系統(tǒng)根據(jù)配置自動生成。 這部分代碼涉及我的系統(tǒng)和框架比較深,所以不帖代碼了哈,大家自己搞搞2天也就出來了


          還做了個及其變態(tài)的功能,就是把界面上所有顯示的jpivot cell,一個個的去取出鉆取數(shù)據(jù)的measure,然后生成csv文件,打成zip包給用戶下載或發(fā)到其他接口。 當時我化了整整一個禮拜鉆研mondrian代碼,希望可以不用那么傻傻個一個個去鉆,結果失敗...

          我在用Jpivot的時候,發(fā)現(xiàn)用mondrian是影響取數(shù)性能其中的一個瓶頸........ 經(jīng)研究.....我們自己修改了jpivot和wcf的一些代碼來適應我們自己的項目.........以下是我做的一些修改.....想聽聽大家的意見 1.脫離mondrian.直接寫dll的方式取數(shù),然后生成XML數(shù)據(jù) .我發(fā)現(xiàn)脫離mondrian自己寫了一個DLL去調用MSSQL 2000 的OLAP,數(shù)度很快........... 2 .修改界面的顯示方式 上面也說道.Jpivot的界面一個不好看,二是用起來很不方便.比如取維度等的時候....一層一層的進去實在很麻煩.... a.修改取維度的方式 我們參照ms的做法 做成一個了一個樹的取數(shù),研究jpivot里面的代碼.如果直接用jpivot的代碼取數(shù)據(jù)十分慢.這樣我自己通過AJAX和Jpivot結合,動態(tài)生成樹的結構,然后在樹上取維度的時候,直接通過鼠標托到選擇維度textbox上.........依照條件生成相應MDX....顯示數(shù)據(jù)..... b.修改數(shù)據(jù)顯示的樣式.和取維度,生成MDX分開了. 顯示數(shù)據(jù)我用了另外一種方式顯示.就是用Frame分為上下兩層.....上下兩層可以通過按鈕擴大整個頁面........ 3. 集成在自己的框架中 集成在自己的框架中,我個人覺得是比較麻煩的一件事情.一點小事沒有搞好就很麻煩...因為我們是用JSF開發(fā)的.所以依照Jpivot....自己寫了一些組件來輔助開發(fā),我自己開發(fā)主要改成比較像ms 2000 的olap分析方法... 還未完成的需求 JFreeChar的功能還需要加強. 個人感覺:jpivot是很不錯.可是不能一拿來就用..我發(fā)現(xiàn)好多人用jpivot都要修改好多東西....但是修改起來又比較麻煩....java,j2ee,xml ,xslt,javascript,taglib.....好多東西都要懂.....
          posted @ 2008-03-26 22:28 edsonjava 閱讀(2244) | 評論 (1)編輯 收藏
           
          主站蜘蛛池模板: 德令哈市| 城市| 体育| 韩城市| 娱乐| 庄浪县| 黄骅市| 威信县| 抚松县| 洛川县| 罗城| 开封市| 龙陵县| 宕昌县| 宁河县| 青海省| 新巴尔虎右旗| 英吉沙县| 彭水| 奎屯市| 肃南| 鄂温| 民乐县| 黎平县| 资溪县| 汉沽区| 云南省| 会昌县| 山丹县| 罗山县| 长治市| 富民县| 象山县| 兴文县| 衡水市| 安庆市| 通山县| 临夏市| 且末县| 景宁| 宜兰市|