<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>jjjava</title>
    <description></description>
    <link>http://jjjava.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>商业智能需要站在全局角度考虑问题</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/174452" style="color:red;">http://jjjava.javaeye.com/blog/174452</a>&nbsp;
          发表时间: 2008年03月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          首先看一下下面这个表样.这个表样是润乾的一个示例表样,接着介绍birt 是如何做的<br />[img]http://jjjava.javaeye.com/upload/picture/pic/9994/c5064865-dcf6-393e-<br />b40e-8a64b1ee2dae.jpg[/img]<br />这个表样算是报表中最常见的一种需求了，把不同粒度的数据聚合到同一粒度上.<br /><br />我们用automobile 表示汽车表, 用houseproperty 表示房产表, 用estate表示土地表,用others 表示其他表.他们都有customerid 来表示客户名称.customers 表有customerid 和customername<br /><br />1. 用视图来拼数据<br /><br />   对于  automobile 聚合使用一个autoview , sql 如下<br /><br />   select sum(automobile price* quantity) autototal, customerid  from automobile group by customerid<br /><br />  对于 houseproperty 使用如下view<br /><br />   select sum( house price * quantity ) housetotal, customerid  from houseproperty group by customerid<br /><br />  对于 土地和其他也是差不多类型的sql<br /><br /> <br /><br />  得到了上面这四个视图之后, 就把customers 表根据customerid 和其他四个视图join 起来.<br /><br />  select customername ,  autototal  , housetotal , estatetotal , othertotal<br /><br />   from  customers c , automobile a , houseproperty h , estate e , others o<br /><br />   where 四个视图和customers的连接条件<br /><br /> <br /><br />  由于这个表样并不涉及到以 汽车，房产，土地， 其他表中的任何一个客户为主, 所以暂时也不考虑左右连接的问题.<br /><br /> <br /><br />2. 使用Birt 的Joined Data Set<br /><br />   Birt 提供的Joined Data Set 跟数据库里面的视图是差不多的概念，使不过一个是在数据库内部join 数据，一个是使用Java 循环的方式join 数据.<br /><br />   跟上面创建视图一样，创建四个DataSet , 输出两个字段: customerid 和 total.<br /><br />   然后创建一个Joint Data Set , 把customers 表和 autototal DataSet 按照customerid join起来.这时得到四个字段 customers.customername , customers.customerid  ,  auto DataSet.customerid ，auto DataSet.autotal . 最后我们把这个Joint DataSet 命名为jdataSet1 (代表的是autoDataSet 和 customers 产生的Joint DataSet ).<br /><br />  然后继续创建另一个Joint Data Set 把customers 的customerid 和前一步创建的jDataSet1 按照customerid join 起来得到一个第二个Joint DataSet1 ,我们命名为jDataSet2 .<br /><br />  以此类推，最后我们输出5个字段: customers.name   ,   auto.total ,  house.total  , estate.total , others.total , 实际输出可能在customers.customerid 上重复了4次.<br /><br /> <br /><br />上面两种方式报表的做法主要有两点差别:<br /><br />1. 性能<br /><br />    如果本身数据库单独执行一个视图的sql 结果比较小，而本身的automobile 表数据量比较大（也就是说一个customer对非常多的automobile 记录) , 那么使用数据库视图就会比较慢. 因为数据库在尝试得到4个视图的结果进行了一些不必要的按照automobiel表的customerid和customers的customerid进行的比较操作( 如果有索引肯定是对索引进行了多次不必要的读) ,这时候使用Java的这种循环方式会比较快一点 . 如果本身结构集比较大，那么还是用数据库本身的排序和join 比较快, 这个道理比较类似于数据库中如果结构集大于5% 就不要走索引,直接进行全表扫描.只不过这是一个java 版的.<br /><br />2. 左右连接的问题<br /><br />   如果这个表的数据不是以customers里面的数据为主，而是以四个视图其中的一个为主.这时候要情况可能会比较复杂一些.由于我不太清楚birt 里面joint data set 计算的方式是怎样的，所以也不太好评论.不过如果不使用joint data set , 就是使用一般的编程的方式.那么按照下面这个思路会比较好:<br /><br />a , b , c , d ,e  为customers , automobiles view  (后面简写avlist 表示这个集), housetotal view , 里面的指针.  四个view 都已经排好了序.group by 是默认排序的. outlist 表示最后需要的输出 , row表示最后输出的一条数据<br /><br />for ( 按照主数据循环)  {<br /><br />    row.customerid = customers.customerid;<br /><br />    if( customers.customerid == avlist[b].customerid) {<br /><br />           outlist[x].autotaol = avlist[b].autotal ;<br /><br />           b++<br /><br />     }<br /><br />    四个view 同一个判断方式, 但是每个view 的指针指的是不一样的.<br /><br />    最后:   outlistSet . add (outlist[x])<br /><br />}<br /><br /> <br /><br />如果数据源本身的数据量也很大，需要输出的数据也很多，则上面两种方式都会有性能问题，这时可以考虑商业智能里面的万金油方式: ETL<br /><br /> <br /><br />3. ETL<br /><br />    从上面这个表样看来，可能会有两个隐含条件.一个是聚合的数据粒度在时间上是月，另一个在销售地点粒度上是：支行086001-301 , 所以用ETL一开始就聚合数据可能会更好的解决性能问题.另外一个是如果用户想要排序和过滤数据的话用一个单独的ETL聚合表也比拼数据的方式好的多.<br /><br /> <br /><br />这篇文章的目的并不只是想解释一个做表的问题，而是说明商业智能的一些问题不光需要站在一个独立的角度思考，有些问题本身可能随着环境的一些变化而采取对应的措施，比如上面为了解决排序，过滤，左右连接，性能问题都需要从不同的角度来考虑问题.有时候可能一个做表的问题不光只是要限定在sql 或某个报表软件的本身，有时候某个ETL问题可能不关只是ETL就能解决的,随着情况的复杂可能需要从整个商业智能的全局来进行考虑，商业智能越来越倾向与多个解决方法的融合.<br /><br />本文原文在 http://www.gemini5201314.net<br /><br />如果你对ETL中性能优化问题有兴趣的话，也可以查看另一篇关于在ETL中性能优化要站在全局的角度，而不是只在数据库角度的文章.
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/174452#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 21 Mar 2008 12:26:11 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/174452</link>
        <guid>http://jjjava.javaeye.com/blog/174452</guid>
      </item>
      <item>
        <title>在应用程序中集成Kettle</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/174091" style="color:red;">http://jjjava.javaeye.com/blog/174091</a>&nbsp;
          发表时间: 2008年03月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在应用程序中集成Kettle<br /><br />摘要：本文主要讨论如何在你自己的Java应用程序中集成Kettle<br /><br /> <br /><br />如果你需要在自己的Java应用程序中集成Kettle , 一般来说有两种应用需求，一种是通过纯设计器来设计ETL转换任务，然后保存成某种格式，比如xml或者在数据库中都可以，然后自己调用程序解析这个格式，执行这种转换，是比较抽象的一种执行方式，ETL里面转换了什么东西我们并不关心，只关心它有没有正常执行。另一种是通过完全编程的方式来实现，详细的控制每一个步骤，需要知道转换执行的成功与否，这种方式可能需要更多的理解kettle的API 以便更好的跟你的应用程序紧密结合，不过难度也比较大，可以很好的定制你的应用程序，代价自然是入门门槛比较高。本文主要向你解释第一种Kettle的集成方式<br /><br />*************************<br />原文地址: <a href="http://www.gemini5201314.net" target="_blank">在应用程序中集成kettle</a>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/174091#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 20 Mar 2008 13:40:08 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/174091</link>
        <guid>http://jjjava.javaeye.com/blog/174091</guid>
      </item>
      <item>
        <title>ETL性能优化</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/174090" style="color:red;">http://jjjava.javaeye.com/blog/174090</a>&nbsp;
          发表时间: 2008年03月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          现有orders 表和 orderdetails 表表示订单和订单的详细情况, 字段如下:<br /><br />orders :     orderid (pk) ,   orderdate  (date) ,  customernumber  (number)<br /><br />orderdetails   :  orderid (pk) ,  orderdetailsid (pk)  , price ,  quantity ,  product_id<br /><br />现在数据库要更新orders 表的数据，级联的就会更新orderdetails 表的数据, 然后我们刷新数据仓库乙的事实表orderdetails , 一开始的执行思路可能是这样的:<br /><br />step1: 从orders 表读某个条件的数据，我们比方说orderdate 大于2008年4月,然后我们只要orderid  ,sql 象下面这个样子<br /><br />select orderid from orders where orderdate &lt; 2008年四月.<br /><br />step2: 把orderid 当成参数传给orderdetails ,然后读取所有符合orders表里面orderid 的orderdetails 记录:<br /><br />select * from orderdetails where orderid = ?   ( 这个？的参数是由前面一个步骤来的)(这个读取的过程是大量循环的读取)<br /><br />step3: 然后把这些orderdetails 记录怎么样到数据仓库乙&hellip;&hellip;..<br /><br />*************<br /><br />step1:<br /><br />select orderdetails.orderid , orderdetailsid , price , quantity , product_id<br /><br />from orders , orderdetails<br /><br />where orders.orderid = orderdetails.orderid<br /><br />and     orders.orderdate &lt; 2008年四月<br /><br />step2:  更新数据仓库乙中的对应数据.<br /><br />两个ETL设计的结果相同，性能天壤之别<br /><br />查看完整版: <a href="http://www.gemini5201314.net/" title="ETL性能优化" target="_blank">ETL性能优化</a><br /><p>&nbsp;</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/174090#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 20 Mar 2008 13:36:01 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/174090</link>
        <guid>http://jjjava.javaeye.com/blog/174090</guid>
      </item>
      <item>
        <title>Kettle的一些应用问题</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/173702" style="color:red;">http://jjjava.javaeye.com/blog/173702</a>&nbsp;
          发表时间: 2008年03月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Kettle的一些应用问题<br /><br />摘要：本文主要介绍使用kettle设计一些ETL任务的时候可能遇到的跟kettle环境有关的一些问题，这些问题大部分都不在官方FAQ上，你可以在kettle的论坛上找到一些问题的答案<br /><br />1. Join<br /><br />我得到A 数据流（不管是基于文件或数据库），A包含field1 , field2 , field3 字段，然后我还有一个B数据流，B包含field4 , field5 , field6 , 我现在想把它们 &lsquo;加&rsquo; 起来, 应该怎么样做.<br /><br />这是新手最容易犯错的一个地方，A数据流跟B数据流能够Join，肯定是它们包含join key ,join key 可以是一个字段也可以是多个字段。如果两个数据流没有join key ,那么它们就是在做笛卡尔积，一般很少会这样。比如你现在需要列出一个员工的姓名和他所在部门的姓名，如果这是在同一个数据库，************************<br /><br /> <br /><br />5 .事务型ETL<br /><br />Kettle里面是没有所谓事务的概念的，每个步骤都是自己管理自己的连接的，在这个步骤开始的时候打开数据库连接，在结束的时候关闭数据库连接，一个步骤是肯定不会跨session的（数据库里面的session）, 另外，由于kettle是并行执行的，所以不可能把一个数据库连接打&times;&times;&times;&times;&times;&times;&times;&times;&times;&times;&times;&times;&times;<br /><br /> <br /><br />7. kettle的性能<br /><br />kettle本身的性能绝对是能够应对大型应用的，一般的基于平均行长100的一条记录，即使源数据库和目标数据库以及kettle都在同一台机器上（最常见的桌面工作模式，双核，1G内存），速度大概都可以到<br /><br />尽量使用数据库连接池<br /><br />尽量提高批处理的commit size<br /><br />尽量使用缓存，缓存尽量大一些<br /><br />Kettle 是Java 做的，尽量用大一点的内存参数启动Kettle.<br /><br />可以使用sql 来做的一些操作尽量用sql<br /><br />Group , merge , stream lookup ,split field 这些操作都是比较慢的，想办法避免他们.<br /><br />插入大量数据的时***********************<br /><br /> <br /><br />10 . 字符集<br /><br /><br />原文地址在我的新blog : http:www.gemini5201314.net
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/173702#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 19 Mar 2008 12:27:41 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/173702</link>
        <guid>http://jjjava.javaeye.com/blog/173702</guid>
      </item>
      <item>
        <title>启用新的Blog地址</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/169520" style="color:red;">http://jjjava.javaeye.com/blog/169520</a>&nbsp;
          发表时间: 2008年03月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          租了一个新的dreamhost 空间，所以今后将启用新的地址:<br />http://www.gemini5201314.net<br />这个Blog还是会偶尔更新一下，不过个人的文档还是会尽量放在新blog上，<br />目前给itpub投了两个系列的稿子都是ETL的，一个关于oracle warehouse builder的教程，好像已经发表了三篇，还有两篇估计要等一段时间，<br /><br />http://publish.itpub.net/db/2007-12-27/200712271916501.shtml      1<br />http://tech.it168.com/db/2008-02-14/200802141542372.shtml        2<br />http://tech.it168.com/db/2008-02-27/200802271433072.shtml        3<br />另外一个系列的是关于另一个ETL工具kettle的，也是五篇文章，不过由于itpub处理稿件比较慢，肯能会等很长时间.<br />给IBM也投了一篇关于数据仓库建模的，用的IBM Rational Data Architect ， 编辑没和我联系，不知道是不是技术水平不够，另外还有几篇关于使用开源报表工具Birt创建中国式报表的文章和真正的OLAP应该是什么样的文章也在等着itpub的审阅，不过他们的速度的确不敢恭维，今后可能不太会在javaeye写大段的文章了，请各位朋友也不要给我发javaeye的站内短信了,如果有什么事情可以给我发email:<br />gemini5201314 在 gmail.com 或者 jj12tt  在  yahoo.com.cn<br />把”在“改成@ , 尽量加上标题比如 ：切磋ETL问题  或  讨论制作报表问题 ，以免被当成垃圾邮件自动被过滤掉了.<br />ETL只关心kettle<br />报表只关心Birt<br />BI平台只关心pentaho<br />仍然专注商业智能
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/169520#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 09 Mar 2008 14:28:55 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/169520</link>
        <guid>http://jjjava.javaeye.com/blog/169520</guid>
      </item>
      <item>
        <title>Talend 的市场策略</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/162772" style="color:red;">http://jjjava.javaeye.com/blog/162772</a>&nbsp;
          发表时间: 2008年02月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近在jroller 看到一篇颇搞笑的文章，讲的是一个开源的ETL工具提供商Talend 的市场策略问题，原文地址是<br /><br />http://www.jroller.com/andyl/entry/talen_d_ed_marketing<br /><br />作者说我爱开源，我爱eclipse, 所以我也应该喜欢基于eclipse 的商业公司.非常不幸，并不是这样的.<br /><br />在eclipse 官方的plugincentral 里面，作者发现了talend的的用户评分都是10分，而且那句<br /><br />they art of creative rating at EPIC 也特搞笑，然后他给了一张图显示那些给 talend 的打分<br /><br />那些家伙给其他plugin 打分都是1 分，也太假了吧，你宣传产品就宣传啦，也不用打击别人的东西吧，<br /><br />eclipseplugincentral 也算是非常大的一个用户社区了，里面排得上名的都是像MyEclipse ,SpirngIDE , Subversive 这样非常流行和实用的插件，最近Pulse 也很流行，talend 靠着非常热心和狂热的用户一举得到高投票，又正巧被作者发现了<br /><br />我过去看这个插件排名的时候，还有几个10分摆在那，不过更多的是1分，（估计里面不能打0分或者负数）<br /><br />其实talend  的产品我也试用过，不算太好，也不算太差，虽然不像MyEclipse 那样高用户评价，但至少也能有各5到7分吧，<br /><br />这一下反到把自己搞臭了。看后面的品论好像有一个eclipse 的负责的说，如果这是一个乱用匿名投票，我们将对其进行惩罚，他们组织在六个月之前都已经开始注意这个事情了，在JDJ (也是一个国外的非常大的用户社区）看到talend获得很高的投票也觉得很奇怪。<br /><br />现在倒好，估计再也不能上plugincentral 了.<br /><br />唉，这事放在国内也就一正常的产品宣传问题，只不过国外有人较真了，这一较真人家就开始有人管了，看来Web2.0 最可怕的还是用户参与，一个东西真的被交流起来，好就是好，不好就是不好，想想国内多少企业宣传，随便做一个报表就号称行业领先商业智能解决方案，随便开发一个信息管理系统就是技术先进的行业ERP，CRM,XXX 企业应用解决方案，东西还真的不能比，万一大家一比比出个什么两边对骂出来还真的蛮无聊的<br /><br />凭心而论，用talend 来做ETL也算可以，不过个人更倾向与用kettle ,记得以前kettle 论坛上有一个人说自己用kettle 解决了什么什么项目（差不多就是表扬信），人家主开发者就一句话：这样的发言毫无用处，有bug报bug,有request报request, 没事的回去洗了睡（原话当然不是这样) , 这可是在自己的地盘呀，估计那些牛人也是不做饭不知柴米油盐贵呀，好歹说个客套话啦.<br /><br />宣传自己就宣传自己拉，别乱说别人不好沙，产品实力有多少先不说，人品呀，人品.
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/162772#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 17 Feb 2008 13:55:06 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/162772</link>
        <guid>http://jjjava.javaeye.com/blog/162772</guid>
      </item>
      <item>
        <title>itpub上爆笑贴：Effective Oracle By Design第八章怎么来的</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/101065" style="color:red;">http://jjjava.javaeye.com/blog/101065</a>&nbsp;
          发表时间: 2007年07月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font size="4">学习oracle 的人都知道Tom 吧，tom 有三本书非常的经典.<br />
1 . <expert one="" on="" oracle="">Expert one on one Oracle<br />
<br />
2 . Expert oracle database Archetecure 9i and 10g Programming Techniques and Solutions<expert and="" solutions="" programming="" database="" archetecure="" techniques="" oracle=""><br />
<expert and="" solutions="" programming="" database="" archetecure="" techniques="" oracle=""><expert and="" solutions="" programming="" techniques="" archetecure="" database="" oracle=""><expert and="" solutions="" programming="" techniques="" archetecure="" database="" oracle=""><br />
3 . <effective by="" design="" oracle="">Effective oracle by design<br />
第一本书虽然是讲的8i 的，但是到了现在11g 都发布了，这本书仍然是每个oracle 学习者的必备书籍之一，第二本书比较适合现在看，毕竟还是比较多的提到了9i 和10g .第三本书大家都知道网上面是没有完整的PDF 版的，只有几个章节的, 好像1,2,3,7章是tom 放在他的专栏里面的,然而第八章的出现完全要归功与itpub 上的一位maozq 朋友，他发email 向tom 要的，而且这个email 超级爆笑, itpub 上有这个有趣的故事的讨论<br />
<a href="http://www.itpub.net/221173,2.html" target="_blank">http://www.itpub.net/221173,2.html</a><br />
<br />
下面是他向tom 要书的email template:<br />
<br />
</effective></expert></expert></expert></expert></expert></font><font size="2" face="verdana, arial, helvetica"><span class="javascript" id="text5269041" style="font-size: 12px;"><font size="4">Dear Mr. Tom,<br />
<br />
I am XXX, one of your big fans. I have bought your both Export Oracle and Effective Oracle books. They are definitely the best Oracle books in this planet. Thanks for your great contribution to help me(and whole Oracle users community) to understand Oracle and develop high-performance Oracle applications.<br />
<br />
However, I just wonder whether I can have an e-version of </font>  <effective oracle=""><font size="4">, so I can read and refer it on my laptop? The big is too big to carry ... If I cann't have the whole book, I like XXX chapter the most, can you just give me this chapter? I promise I will just keep it on my personal computer and never distribute it.<br />
<br />
Thanks!!!<br />
<br />
XXX</font>  <br />
<br />
<br />
<font size="4">从这个email template 可以看到两个经典的地方：<br />
1 . email 的template 的确是经典之极，我已经把这个email 的template 收进了我的收藏模板了，以后找别人要东西就follow 这个模板就可以了.<br />
2 . 关键是这个点子非常的妙，不用自己花钱买一本然后用扫描仪搞出个PDF ,直接要作者本人要，羊毛出在羊身上呀.<br />
<br />
最近比较闲着没事，然后又被指派当QA 的technical support, 然后QA mm 就老是抱怨说性能很差，于是就看看oracle 的tuning 资料，然后还做了一svn 方面的log 研究，具体看http://jjjava.javaeye.com/admin/show/101063<br />
</font></effective></span></font>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/101065#comments" style="color:red;">已有 <strong>1</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 14 Jul 2007 22:31:17 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/101065</link>
        <guid>http://jjjava.javaeye.com/blog/101065</guid>
      </item>
      <item>
        <title>关于Daily Build的ant 脚本中列出svn log 的方法</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/101063" style="color:red;">http://jjjava.javaeye.com/blog/101063</a>&nbsp;
          发表时间: 2007年07月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font size="4">最近闲着没事，真的是很闲，居然要我去看看oracle数据库performance tuning,而且应为太闲，发现了effective oracle by design 的第八章了，是itpub 上的一位会员找tom ，要的，这个帖子在 </font><font size="4">http://www.itpub.net/221173,2.html , 超爆笑，具体请看我的另一篇文章</font></p>
<font size="4">http://jjjava.javaeye.com/admin/show/101065</font><br />
<p> </p>
<p><font size="4">因为公司的QA抱怨说速度很慢,我们只有Stage环境，生产环境不在我们这边，公司唯一的一个DBA 被派去做enhancement 了(汗) ,于是被指派研究如何在ant 脚本中显示svn 中的commit 消息.需求大概是这样的:</font></p>
<p><font size="4">每次commit 的时候我们都会填写commit 的message , 比如 bug fix #98435 : &lt;<bug description="">&gt; 或者类是 EN #19841 : &lt;<xxxx enhancement="">&gt; , 然后我们的Stage 环境，就是大家可以公共访问的环境也同时提供给QA 做test 的环境，每天会更新两次早上8：30一次（这个时候大家还没有上班），然后下午5：00一次（我们6:00下班），8：30更新的时候公司没人，主要是针对昨天新做完的EN 和 5点过后check in  的bug , 5：00 的更新最要是让QA 做Bug verify (因为每天结束了，Team Leader 要把bug 发到美国那边去，美国那边就不用做重复的工作了) .我们以前有什么check in 都是Team Leader 发邮件给QA , 告诉他们那些bug check in 了，那些enhancement check in 了，然后全部都是靠搜集我们每天提交给他的work list , 然后他就凭脑袋记住然后发邮件给QA , 这样一个是容易出错，有可能是我们自己写的work list 出错了，比如写错了bug number ,另一个是Team Leader 忘记搜集某个人work list 了( 我们不用issue tracking 工具，因为美国那边认为不值得花钱买一个JIRA , 而且他们相信他们用手工的方式工作了多年也没有什么很大的问题，即使我们自己用开源的issue tracking 工具,他们也拒绝合作，强吧），所以就要我写个ant script 来自动在邮件里面列出更新了bug 或者enhancement.</xxxx></bug></font></p>
<p><font size="4">现在的情况：<br />
我们已经有ant script 可以执行 更新code  &gt;   编译code  &gt;   混淆 code  &gt;  最后发邮件给所有人 ， 我们更新的时候是用的windows 系统的task scheduler.</font></p>
<p><font size="4">改变之后的状态：<br />
update 的时候要有update log 和 更新的文件列表 , 邮件里面要有update.log 的消息</font></p>
<p><font size="4">方便QA  快速知道开发的状态.</font></p>
<p><font size="4">用ant 脚本来更新code 都是用的svnkit 包，首先下载svnkit 包, 大概是以下几个文件，svnkit.jar  ,   svnant.jar  ,  <strong>SvnClientAdapter</strong></font><font size="4">.jar  ，svnjavahl.jar（文件名记得不是很清楚了）,放到ant 的lib 目录下面, 具体参考http://subclipse.tigris.org/svnant.html  上面的文档.</font></p>
<p><font size="4">我查了一下如何显示svn 的update log 方法 : </font></p>
<p><font size="4">http://svnbook.red-bean.com/en/1.0/re15.html</font></p>
<p><font size="4">你要先装svn 的客户端（运行这个例子的时候需要，不是你用svnkit 的时候需要)</font></p>
<p><font size="4">然后    </font></p>
<p><font size="4">svn log [PATH]</font></p>
<p><font size="4">svn log URL [PATH...]<br />
<br />
它有几个参数:<br />
--revision (-r) REV<br />
--quiet (-q)<br />
--verbose (-v)<br />
--targets FILENAME<br />
--stop-on-copy<br />
--incremental<br />
--xml<br />
--username USER<br />
--password PASS<br />
--no-auth-cache<br />
--non-interactive<br />
--config-dir DIR<br />
<br />
比如： <br />
svn log http://svn.red-bean.com/repos/test/foo.c<br />
它会列出所有的foo.c 这个文件的所有修改历史<br />
<br />
svn log http://svn.red-bean.com/repos<br />
它会列出你整个项目的修改历史<br />
<br />
<font color="#000000">svn log http://</font></font><font size="4">svn.red-bean.com/repos </font><font size="4" color="#000000">-r 14 &gt;mylog.txt<br />
svn log http://svn.red-bean.com/repos -r 19&gt;&gt;mylog.txt<br />
svn log http://svn.red-bean.com/repos -r 20&gt;&gt;mylog.txt<br />
它会先创建一个revision 14 的mylog.txt 文件，后面两个命令会把revision 19 个和revision 20 的log 加入到mylog.txt 文件中.<br />
关于svn log 命令行的详细用法请参考 <br />
</font><font size="4">http://svnbook.red-bean.com/en/1.0/re15.html</font></p>
<p><font size="4"><br />
</font></p>
<p><font size="4">接着我就研究怎么样在ant script 里面加入svn 的log 信息.</font></p>
<p><font size="4">我发现打开svnant.jar 包的时候里面有个 svn.xml 文件，里面记录的就是所有svnkit 支持的svn ant task . 其中只需要一个就够了，</font></p>
<p><font size="4"><taskdef name="svn" classname="org.tigris.subversion.svnant.SvnTask"></taskdef></font></p>
<p><font size="4">接着我就写script , <br />
</font></p>
<p><font size="4"><taskdef name="svn" classname="org.tigris.subversion.svnant.SvnTask"></taskdef></font></p>
<p><font size="4"><!-- Update Your Project code --><target name="updateSVN"><svn username="xxxUser" javahl="true" password="xxxPassword"><svn javahl="true"><log destfile="revision.log"></log></svn></svn></target></font> </p>
<div class="code_title">xml 代码</div>
<div class="dp-highlighter">
<div class="bar"> </div>
<ol class="dp-xml" start="1">
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">target</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">&quot;updateSVN&quot;</span><span> </span><span class="tag">&gt;</span><span>  </span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;    <span class="tag">&lt;</span><span class="tag-name">svn</span><span> </span><span class="attribute">username</span><span>=</span><span class="attribute-value">&quot;XXX&quot;</span><span> </span><span class="attribute">password</span><span>=</span><span class="attribute-value">&quot;XXX&quot;</span><span> </span><span class="attribute">javahl</span><span>=</span><span class="attribute-value">&quot;true&quot;</span><span class="tag">&gt;</span><span>  </span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        <span class="tag">&lt;</span><span class="tag-name">update</span><span> </span><span class="attribute">dir</span><span>=</span><span class="attribute-value">&quot;${XXX}&quot;</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li>
    <li class=""><span>    <span class="tag"><!--</span--><span class="tag-name">&nbsp;&nbsp;&nbsp;&nbsp; &lt;/svn</span><span class="tag">&gt;</span><span>  </span></span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;    <span class="tag">&lt;</span><span class="tag-name">svn</span><span> </span><span class="attribute">javahl</span><span>=</span><span class="attribute-value">&quot;true&quot;</span><span class="tag">&gt;</span><span>  </span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        <span class="tag">&lt;</span><span class="tag-name">log</span><span> </span><span class="attribute">destfile</span><span>=</span><span class="attribute-value">&quot;revision.log&quot;</span><span>  </span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="attribute">path</span><span>=</span><span class="attribute-value">&quot;${XXX}&quot;</span><span>  </span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                <span class="attribute">asXml</span><span>=</span><span class="attribute-value">&quot;false&quot;</span><span>  </span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                <span class="attribute">startRevision</span><span>=</span><span class="attribute-value">&quot;HEAD&quot;</span><span>  </span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                <span class="attribute">stopRevision</span><span>=</span><span class="attribute-value">&quot;PREV&quot;</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li>
    <li class="alt"><span>    <span class="tag"><!--</span--><span class="tag-name">&nbsp;&nbsp;&nbsp;&nbsp; &lt;/svn</span><span class="tag">&gt;</span><span>  </span></span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;    <span class="tag">&lt;</span><span class="tag-name">echo</span><span> </span><span class="attribute">message</span><span>=</span><span class="attribute-value">&quot;Update finished successfully, please see attached for version information!&quot;</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li>
    <li class="alt"><span><span class="tag"><!--</span--><span class="tag-name">&lt;/target</span><span class="tag">&gt;</span><span>  </span></span></span></li>
</ol>
</div>
<font size="4"><target name="updateSVN"><svn username="xxxUser" javahl="true" password="xxxPassword"><svn javahl="true"><echo message="Update finished successfully, please see revision.log for version information!"></echo></svn></svn></target></font>
<p> </p>
<p><font size="4"><target name="updateSVN"><svn username="xxxUser" javahl="true" password="xxxPassword"><svn javahl="true"><echo message="Update finished successfully, please see revision.log for version information!"><br />
</echo></svn></svn></target></font></p>
<p><font size="4"></font></p>
<p><font size="4">其中startRevision 和 stopRevision 的值可以是</font></p>
<dl><dt><font size="4"><span class="term"><a id="svn.tour.revs.keywords">HEAD :  </a></span><a id="svn.tour.revs.keywords">版本库中最新的（或者是&ldquo;<span class="quote">最年轻的</span>&rdquo;）版本。</a></font></dt><dt><font size="4"><span class="term"><a id="svn.tour.revs.keywords">BASE  :  </a></span><a id="svn.tour.revs.keywords">工作拷贝中一个条目的修订版本号，如果这个版本在本地修改了，则&ldquo;<span class="quote">BASE版本</span>&rdquo;就是这个条目在本地未修改的版本。</a></font></dt><dt><font size="4"><span class="term"><a id="svn.tour.revs.keywords">COMMITTED :  </a></span><a id="svn.tour.revs.keywords">在<code class="literal">BASE</code>版本之前（或在Base）一个项目最后修改的版本。</a></font></dt><dt><font size="4"><span class="term"><a id="svn.tour.revs.keywords">PREV  :  </a></span><a id="svn.tour.revs.keywords">一个项目最后修改版本<span class="emphasis"><em>之前</em></span>的那个版本（技术上为COMMITTED -1）。</a></font></dt></dl>
<p><font size="4">这段代码就是在你的script 目录下面会产生一个revision.log 文件，大概这样的格式</font></p>
<p><font size="4">------------------------------------------------------------------------<br />
r14 | ... xxx bug fix #123456 :xxx <br />
<br />
------------------------------------------------------------------------<br />
r15 | ... xxx en #123456 : xxx<br />
<br />
------------------------------------------------------------------------<br />
<br />
然后发邮件:<br />
<target name="email" depends="obfuscate"> <mail mailhost="xxx.xxx.xxx"><from name="xxx" address="developers@xxx.com"></from></mail></target></font></p>
<p><font size="4"><target name="email" depends="obfuscate"><mail mailhost="xxx.xxx.xxx"><from name="xxx" address="developers@xxx.com"> </from></mail></target></font></p>
<div class="code_title"><font size="4"><font>xml 代码</font></font></div>
<div class="dp-highlighter">
<div class="bar"><font size="4"> </font></div>
<ol class="dp-xml" start="1"><font size="4"><font>
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">target</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">&quot;sendmail&quot;</span><span> </span><span class="attribute">depends</span><span>=</span><span class="attribute-value">&quot;obfuscate&quot;</span><span class="tag">&gt;</span><span>  </span></span></li>
    <li class=""><span>    <span class="tag">&lt;</span><span class="tag-name">mail</span><span> </span><span class="attribute">mailhost</span><span>=</span><span class="attribute-value">&quot;XXX.XXX.XXX&quot;</span><span>  </span></span></li>
    <li class="alt"><span>             <span class="attribute">subject</span><span>=</span><span class="attribute-value">&quot;Stage Updated at ${updatetime}&quot;</span><span>  </span></span></li>
    <li class=""><span>             <span class="attribute">messagefile</span><span>=</span><span class="attribute-value">&quot;revision.log&quot;</span><span>  </span></span></li>
    <li class="alt"><span>             <span class="attribute">files</span><span>=</span><span class="attribute-value">&quot;result.log&quot;</span><span class="tag">&gt;</span><span>  </span></span></li>
    <li class=""><span>             <span class="tag">&lt;</span><span class="tag-name">from</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">&quot;Stage Update Agent&quot;</span><span> </span><span class="attribute">address</span><span>=</span><span class="attribute-value">&quot;developers@XXX.con&quot;</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li>
    <li class="alt"><span>             <span class="tag">&lt;</span><span class="tag-name">to</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">&quot;Developers&quot;</span><span> </span><span class="attribute">address</span><span>=</span><span class="attribute-value">&quot;developers@XXX.con&quot;</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li>
    <li class=""><span>    <span class="tag"><!--</span--><span class="tag-name">mail</span><span class="tag">&gt;</span><span>  </span></span></span></li>
    <li class="alt"><span><span class="tag"><!--</span--><span class="tag-name">target</span><span class="tag">&gt;</span><span>  </span></span></span></li>
    </font></font></ol>
    <font size="4">    </font></div>
    <font size="4">    <br />
    <br />
    最后这样就算是完成了.<br />
    关于svnant 的详细task 请参考  http://subclipse.tigris.org/svnant/svn.html<br />
    关于svn 版本号之间的区别 http://svnbook.subversion.org.cn/1.2/svn.tour.revs.html<br />
    <br />
    </font>
    <p> </p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/101063#comments" style="color:red;">已有 <strong>6</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 14 Jul 2007 22:24:12 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/101063</link>
        <guid>http://jjjava.javaeye.com/blog/101063</guid>
      </item>
      <item>
        <title>pentaho 1.5.5发布</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/101032" style="color:red;">http://jjjava.javaeye.com/blog/101032</a>&nbsp;
          发表时间: 2007年07月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font size="4">pentaho 1.5.5在7月13日发布了，在sf 上已经可以下载了.<br />
7月2日已经收到了pentaho community 的邮件，说从6月18日开始的测试成效非常的好，已经解决了大概280多个issue.<br />
7月12日又再次收到pentaho community 的邮件，说大概有175个JIRA 的 issue 被解决了.<br />
从目前的状态来看,pentaho 大概是准备从1.5.0 ， 每次一个小版本的往上面前进，一直到它的 1.6.0 , 从时间上大概推测是10月份.<br />
我已经介绍过了1.6.0 的新功能了,不过还是为大家列个清单吧:<br />
</font>
<p><font size="4">                       Some of the 1.6 highlights are:<br />
</font>                       </p>
<ul>
    <li><font size="4"><strong>Web-based Ad Hoc Query and Reporting</strong> - easy to use, self-service reporting for the masses</font></li>
    <li><font size="4"><strong>Pentaho Metadata</strong> - enabling self-service reporting by shielding business users from the complexities of underlying data sources and dramatically reduces maintenance costs associated with maintaining your BI deployments </font></li>
    <li><font size="4"><strong>Security</strong> - pluggable security model with the ability to integrate with existing security infrastructures like LDAP and MSAD                        </font></li>
    <li><font size="4"><strong>Subscriptions</strong> - the ability for end users to schedule and configure the delivery of Pentaho content                        </font></li>
    <li><font size="4"><strong>RDBMS repository</strong> - the ability to house the Pentaho Solutions Repository in an RDBMS</font></li>
    <li><font size="4"><strong>Mondrian Schema and Data cache flushing</strong> - ability to flush the Mondrian caches without restarting the server</font></li>
</ul>
<font size="4">最大的功能点还是在Web-based Ad Hoc Query and Reporting 上面，不知道大家有没有下载pentaho 的 demo 来尝尝鲜.一个完全基于Web 的报表设计器，功能和易用性上面都非常的实用.<br />
另外pentaho 的Dashboard 也在重组，正在征求意见，pentaho 想要设计一个新的DashBoard 的设计器，也是基于Web 的，估计会和Web reporting 差不多的，也是pentaho 非常实用的功能点.<br />
从6月18日开始的测试主要是集中在metadata 上面，7月12日开始的第二轮测试主要是集中在了pentaho platform 上面了.<br />
<br />
另外一个非常小的消息，openoffice 已经发布了2.3 的 snapshot 版本，我看了一下清单，八百年前就听说pentaho 跟openoffice 要搞出个什么商业智能的office 版本（八百年小于等于6个月), 不过从列表上来看，好像没有什么更新.<br />
<br />
就这些了，期待pentaho 的下一个版本快点出来.</font>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/101032#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 14 Jul 2007 15:50:30 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/101032</link>
        <guid>http://jjjava.javaeye.com/blog/101032</guid>
      </item>
      <item>
        <title>用Birt API 处理参数问题</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/99887" style="color:red;">http://jjjava.javaeye.com/blog/99887</a>&nbsp;
          发表时间: 2007年07月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font size="4">我们在使用Birt 的时候需要动态处理一些参数问题,所以使用API 来处理参数是Birt 很重要的一部分.所有以 'I' 开头的都是Interface , <br />
Birt 有三种parameter 分别对应 IParameterGroupDefn&nbsp; ,&nbsp; ICascadingParameterGroup ,&nbsp; IScalarParameterDefn , 对应的三个Handler 分别就是<br />
ParameterGroupHandle， CascadingParameterGroupHandle&nbsp; ， ScalarParameterHandle <br />
Engine.shutdown() 已经过时了,应该使用新的Engine.destory(). 不过例子是Birt 官方的,所以我没有修改.<br />
<br />
<br />
import java.io.Serializable;<br />
import java.util.Collection;<br />
import java.util.Collections;<br />
import java.util.HashMap;<br />
import java.util.Iterator;<br />
import java.util.logging.Level;<br />
<br />
import org.eclipse.birt.core.framework.Platform;<br />
import org.eclipse.birt.report.engine.api.EngineConfig;<br />
import org.eclipse.birt.report.engine.api.EngineException;<br />
import org.eclipse.birt.report.engine.api.IGetParameterDefinitionTask;<br />
import org.eclipse.birt.report.engine.api.IParameterDefnBase;<br />
import org.eclipse.birt.report.engine.api.IParameterGroupDefn;<br />
import org.eclipse.birt.report.engine.api.IParameterSelectionChoice;<br />
import org.eclipse.birt.report.engine.api.IReportEngine;<br />
import org.eclipse.birt.report.engine.api.IReportEngineFactory;<br />
import org.eclipse.birt.report.engine.api.IReportRunnable;<br />
import org.eclipse.birt.report.engine.api.IScalarParameterDefn;<br />
import org.eclipse.birt.report.model.api.CascadingParameterGroupHandle;<br />
import org.eclipse.birt.report.model.api.ReportDesignHandle;<br />
import org.eclipse.birt.report.model.api.ScalarParameterHandle;<br />
public class ParametersTask {<br />
<br />
static void executeReport() throws EngineException<br />
{<br />
&nbsp;HashMap&lt;String, HashMap&lt;String, Serializable&gt;&gt; parmDetails = new HashMap&lt;String, HashMap&lt;String, Serializable&gt;&gt;();<br />
<br />
&nbsp;IReportEngine engine=null;<br />
&nbsp;EngineConfig config = null;<br />
&nbsp;try{<br />
&nbsp; config = new EngineConfig( );<br />
&nbsp; config.setEngineHome( &quot;C:/birt-runtime-2_1_1/birt-runtime-2_1_1/ReportEngine&quot; );<br />
&nbsp; config.setLogConfig(null, Level.FINE);<br />
<br />
&nbsp; Platform.startup( config );<br />
&nbsp; IReportEngineFactory factory = (IReportEngineFactory) Platform<br />
&nbsp; .createFactoryObject( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY );<br />
&nbsp; engine = factory.createReportEngine( config );<br />
&nbsp; engine.changeLogLevel( Level.WARNING );<br />
<br />
&nbsp;}catch( Exception ex){<br />
&nbsp; ex.printStackTrace();<br />
&nbsp;}<br />
<br />
&nbsp;IReportRunnable design = null;<br />
<br />
&nbsp;//Open a report design <br />
&nbsp;design = engine.openReportDesign(&quot;C:/test/2.1/parameters/Parameters.rptdesign&quot;); <br />
<br />
&nbsp;//Create Parameter Definition Task and retrieve parameter definitions<br />
&nbsp;IGetParameterDefinitionTask task = engine.createGetParameterDefinitionTask( design );<br />
&nbsp;Collection params = task.getParameterDefns( true );<br />
<br />
&nbsp;//Iterate over each parameter<br />
&nbsp;Iterator iter = params.iterator( );<br />
&nbsp;while ( iter.hasNext( ) )<br />
&nbsp;{<br />
&nbsp; IParameterDefnBase param = (IParameterDefnBase) iter.next( );<br />
<br />
&nbsp; if ( param instanceof IParameterGroupDefn )<br />
&nbsp; {<br />
&nbsp;&nbsp; IParameterGroupDefn group = (IParameterGroupDefn) param;<br />
&nbsp;&nbsp; //System.out.println( &quot;Parameter Group: &quot; + group.getName( ) );<br />
<br />
&nbsp;&nbsp; // Do something with the parameter group.<br />
&nbsp;&nbsp; // Iterate over group contents.<br />
&nbsp;&nbsp; Iterator i2 = group.getContents( ).iterator( );<br />
&nbsp;&nbsp; while ( i2.hasNext( ) )<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; IScalarParameterDefn scalar = (IScalarParameterDefn) i2.next( );<br />
&nbsp;&nbsp;&nbsp; //System.out.println(&quot;\t&quot; + scalar.getName());<br />
&nbsp;&nbsp;&nbsp; //Get details on the parameter<br />
&nbsp;&nbsp;&nbsp; parmDetails.put( scalar.getName(), loadParameterDetails( task, scalar, design, group));<br />
&nbsp;&nbsp; }<br />
<br />
&nbsp; }<br />
&nbsp; else<br />
&nbsp; {<br />
<br />
&nbsp;&nbsp; IScalarParameterDefn scalar = (IScalarParameterDefn) param;<br />
&nbsp;&nbsp; //System.out.println(param.getName());<br />
&nbsp;&nbsp; //get details on the parameter<br />
&nbsp;&nbsp; parmDetails.put( scalar.getName(),loadParameterDetails( task, scalar, design, null));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; }<br />
&nbsp;}<br />
<br />
&nbsp;//Destroy the engine and shutdown the Platform<br />
&nbsp;//Note - If the program stays resident do not shutdown the Platform or the Engine&nbsp; <br />
&nbsp;engine.shutdown();<br />
&nbsp;Platform.shutdown();<br />
&nbsp;System.out.println(&quot;Finished&quot;);<br />
}<br />
&nbsp;<br />
//Function to load parameter details in a map.<br />
private static HashMap&lt;String, Serializable&gt; loadParameterDetails(IGetParameterDefinitionTask task, IScalarParameterDefn scalar, IReportRunnable report, IParameterGroupDefn group)<br />
{<br />
<br />
<br />
&nbsp;<br />
&nbsp;HashMap&lt;String, Serializable&gt; parameter = new HashMap&lt;String, Serializable&gt;();<br />
<br />
&nbsp;if( group == null){<br />
&nbsp; parameter.put(&quot;Parameter Group&quot;, &quot;Default&quot;);<br />
&nbsp;}else{<br />
&nbsp; parameter.put(&quot;Parameter Group&quot;, group.getName());&nbsp;&nbsp; <br />
&nbsp;}<br />
&nbsp;parameter.put(&quot;Name&quot;, scalar.getName());<br />
&nbsp;parameter.put(&quot;Help Text&quot;, scalar.getHelpText());<br />
&nbsp;parameter.put(&quot;Display Name&quot;, scalar.getDisplayName());<br />
&nbsp;//this is a format code such as&nbsp; &gt; for UPPERCASE<br />
&nbsp;parameter.put(&quot;Display Format&quot;, scalar.getDisplayFormat());<br />
<br />
&nbsp;if( scalar.isHidden() ){<br />
&nbsp; parameter.put(&quot;Hidden&quot;, &quot;Yes&quot;);<br />
&nbsp;}else{<br />
&nbsp; parameter.put(&quot;Hidden&quot;, &quot;No&quot;);<br />
&nbsp;}<br />
&nbsp;if( scalar.allowBlank() ){<br />
&nbsp; parameter.put(&quot;Allow Blank&quot;, &quot;Yes&quot;);<br />
&nbsp;}else{<br />
&nbsp; parameter.put(&quot;Allow Blank&quot;, &quot;No&quot;);<br />
&nbsp;}<br />
&nbsp;if( scalar.allowNull() ){<br />
&nbsp; parameter.put(&quot;Allow Null&quot;, &quot;Yes&quot;);&nbsp;&nbsp; <br />
&nbsp;}else{<br />
&nbsp; parameter.put(&quot;Allow Null&quot;, &quot;No&quot;);<br />
&nbsp;}<br />
&nbsp;if( scalar.isValueConcealed() ){<br />
&nbsp; parameter.put(&quot;Conceal Entry&quot;, &quot;Yes&quot;);&nbsp; //ie passwords etc<br />
&nbsp;}else{<br />
&nbsp; parameter.put(&quot;Conceal Entry&quot;, &quot;No&quot;);<br />
&nbsp;}<br />
<br />
<br />
&nbsp;switch (scalar.getControlType()) {<br />
&nbsp;case IScalarParameterDefn.TEXT_BOX:&nbsp; parameter.put(&quot;Type&quot;, &quot;Text Box&quot;); break;<br />
&nbsp;case IScalarParameterDefn.LIST_BOX:&nbsp; parameter.put(&quot;Type&quot;, &quot;List Box&quot;); break;<br />
&nbsp;case IScalarParameterDefn.RADIO_BUTTON:&nbsp; parameter.put(&quot;Type&quot;, &quot;List Box&quot;); break;<br />
&nbsp;case IScalarParameterDefn.CHECK_BOX:&nbsp; parameter.put(&quot;Type&quot;, &quot;List Box&quot;); break;<br />
&nbsp;default: parameter.put(&quot;Type&quot;, &quot;Text Box&quot;);break;<br />
&nbsp;}<br />
<br />
<br />
&nbsp;switch (scalar.getDataType()) {<br />
&nbsp;case IScalarParameterDefn.TYPE_STRING:&nbsp; parameter.put(&quot;Data Type&quot;, &quot;String&quot;); break;<br />
&nbsp;case IScalarParameterDefn.TYPE_FLOAT:&nbsp; parameter.put(&quot;Data Type&quot;, &quot;Float&quot;); break;<br />
&nbsp;case IScalarParameterDefn.TYPE_DECIMAL:&nbsp; parameter.put(&quot;Data Type&quot;, &quot;Decimal&quot;); break;<br />
&nbsp;case IScalarParameterDefn.TYPE_DATE_TIME:&nbsp; parameter.put(&quot;Data Type&quot;, &quot;Date Time&quot;); break;<br />
&nbsp;case IScalarParameterDefn.TYPE_BOOLEAN:&nbsp; parameter.put(&quot;Data Type&quot;, &quot;Boolean&quot;); break;<br />
&nbsp;default:&nbsp; parameter.put(&quot;Data Type&quot;, &quot;Any&quot;); break;<br />
&nbsp;}<br />
<br />
<br />
&nbsp;//Get report design and find default value, prompt text and data set expression using the DE API<br />
&nbsp;ReportDesignHandle reportHandle = ( ReportDesignHandle ) report.getDesignHandle( );<br />
&nbsp;ScalarParameterHandle parameterHandle = ( ScalarParameterHandle ) reportHandle.findParameter( scalar.getName() );<br />
&nbsp;parameter.put(&quot;Default Value&quot;, parameterHandle.getDefaultValue());<br />
&nbsp;parameter.put(&quot;Prompt Text&quot;, parameterHandle.getPromptText());<br />
&nbsp;parameter.put(&quot;Data Set Expression&quot;, parameterHandle.getValueExpr());<br />
<br />
&nbsp;if(scalar.getControlType() !=&nbsp; IScalarParameterDefn.TEXT_BOX)<br />
&nbsp;{<br />
&nbsp; //retrieve selection list for cascaded parameter<br />
&nbsp; if ( parameterHandle.getContainer( ) instanceof CascadingParameterGroupHandle ){<br />
&nbsp;&nbsp; Collection sList = Collections.EMPTY_LIST;<br />
&nbsp;&nbsp; if ( parameterHandle.getContainer( ) instanceof CascadingParameterGroupHandle )<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; int index = parameterHandle.getContainerSlotHandle( )<br />
&nbsp;&nbsp;&nbsp; .findPosn( parameterHandle );<br />
&nbsp;&nbsp;&nbsp; Object[] keyValue = new Object[index];<br />
&nbsp;&nbsp;&nbsp; for ( int i = 0; i &lt; index; i++ )<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; ScalarParameterHandle handle = (ScalarParameterHandle) ( (CascadingParameterGroupHandle) parameterHandle.getContainer( ) ).getParameters( )<br />
&nbsp;&nbsp;&nbsp;&nbsp; .get( i );<br />
&nbsp;&nbsp;&nbsp;&nbsp; //Use parameter default values<br />
&nbsp;&nbsp;&nbsp;&nbsp; keyValue[i] = handle.getDefaultValue();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; String groupName = parameterHandle.getContainer( ).getName( );<br />
&nbsp;&nbsp;&nbsp; task.evaluateQuery( groupName );<br />
<br />
&nbsp;&nbsp;&nbsp; sList = task.getSelectionListForCascadingGroup( groupName, keyValue );<br />
&nbsp;&nbsp;&nbsp; HashMap&lt;Object, String&gt; dynamicList = new HashMap&lt;Object, String&gt;();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
<br />
&nbsp;&nbsp;&nbsp; for ( Iterator sl = sList.iterator( ); sl.hasNext( ); )<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; IParameterSelectionChoice sI = (IParameterSelectionChoice) sl.next( );<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; Object value = sI.getValue( );<br />
&nbsp;&nbsp;&nbsp;&nbsp; Object label = sI.getLabel( );<br />
&nbsp;&nbsp;&nbsp;&nbsp; System.out.println( label + &quot;--&quot; + value);<br />
&nbsp;&nbsp;&nbsp;&nbsp; dynamicList.put(value,(String) label);<br />
<br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; parameter.put(&quot;Selection List&quot;, dynamicList);<br />
<br />
<br />
&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; }else{<br />
&nbsp;&nbsp; //retrieve selection list<br />
&nbsp;&nbsp; Collection selectionList = task.getSelectionList( scalar.getName() );<br />
<br />
&nbsp;&nbsp; if ( selectionList != null )<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; HashMap&lt;Object, String&gt; dynamicList = new HashMap&lt;Object, String&gt;();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp;&nbsp; for ( Iterator sliter = selectionList.iterator( ); sliter.hasNext( ); )<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; IParameterSelectionChoice selectionItem = (IParameterSelectionChoice) sliter.next( );<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; Object value = selectionItem.getValue( );<br />
&nbsp;&nbsp;&nbsp;&nbsp; String label = selectionItem.getLabel( );<br />
&nbsp;&nbsp;&nbsp;&nbsp; //System.out.println( label + &quot;--&quot; + value);<br />
&nbsp;&nbsp;&nbsp;&nbsp; dynamicList.put(value,label);<br />
<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; parameter.put(&quot;Selection List&quot;, dynamicList);<br />
&nbsp;&nbsp; }<br />
&nbsp; }<br />
<br />
&nbsp;}<br />
<br />
<br />
&nbsp;//Print out results<br />
&nbsp;Iterator iter = parameter.keySet().iterator();<br />
&nbsp;System.out.println(&quot;======================Parameter =&quot; + scalar.getName());<br />
&nbsp;while (iter.hasNext()) {<br />
&nbsp; String name = (String) iter.next(); <br />
&nbsp; if( name.equals(&quot;Selection List&quot;)){<br />
&nbsp;&nbsp; HashMap selList = (HashMap)parameter.get(name);<br />
&nbsp;&nbsp; Iterator selIter = selList.keySet().iterator();<br />
&nbsp;&nbsp; while (selIter.hasNext()) {<br />
&nbsp;&nbsp;&nbsp; Object lbl = selIter.next();<br />
&nbsp;&nbsp;&nbsp; System.out.println( &quot;Selection List Entry ===== Key = &quot; + lbl + &quot; Value = &quot; + selList.get(lbl));<br />
&nbsp;&nbsp; }<br />
<br />
&nbsp; }else{<br />
&nbsp;&nbsp; System.out.println( name + &quot; = &quot; + parameter.get(name));&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; }<br />
&nbsp;}<br />
&nbsp;return parameter;<br />
}<br />
<br />
/**<br />
&nbsp;* @param args<br />
&nbsp;*/<br />
public static void main(String[] args) {<br />
&nbsp;try<br />
&nbsp;{<br />
&nbsp; executeReport( );<br />
&nbsp;}<br />
&nbsp;catch ( Exception e )<br />
&nbsp;{<br />
&nbsp; e.printStackTrace();<br />
&nbsp;}<br />
}<br />
<br />
}<br />
<br />
</font>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/99887#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 10 Jul 2007 22:46:51 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/99887</link>
        <guid>http://jjjava.javaeye.com/blog/99887</guid>
      </item>
      <item>
        <title>BIRT Design API 学习</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/97412" style="color:red;">http://jjjava.javaeye.com/blog/97412</a>&nbsp;
          发表时间: 2007年07月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font size="4">以下这个例子来自birt 的官方教材，我没有改动任何的信息.<br />
这个例子演示了从建立DataSource ,然后建立DataSet , 动态的根据输入数据输出report template .<br />
关于Birt 的 API , 在 eclipse 的 help content 里面有，3.3 支持新的基于topic 的search ，可以帮我们简化搜索的topic , 其中有五个API (一共是5个) : Report Object Model API , Report Engine API , Birt Report Scripting API , Open Data Access API , Data Engine API .另外也提供详细的讲解每一个report 的元素的意思.非常好的一份资料 .<br />
<br />
DECreateDynamicTable.java&nbsp; 例子code : <br />
<br />
import java.io.IOException;<br />
import java.util.ArrayList; <br />
<br />
import org.eclipse.birt.core.framework.Platform;<br />
import org.eclipse.birt.report.model.api.CellHandle;<br />
import org.eclipse.birt.report.model.api.DataItemHandle;<br />
import org.eclipse.birt.report.model.api.DesignConfig; <br />
import org.eclipse.birt.report.model.api.ElementFactory;<br />
import org.eclipse.birt.report.model.api.IDesignEngine;<br />
import org.eclipse.birt.report.model.api.IDesignEngineFactory;<br />
import org.eclipse.birt.report.model.api.LabelHandle;<br />
import org.eclipse.birt.report.model.api.OdaDataSetHandle;<br />
import org.eclipse.birt.report.model.api.OdaDataSourceHandle;<br />
import org.eclipse.birt.report.model.api.PropertyHandle;<br />
import org.eclipse.birt.report.model.api.ReportDesignHandle;<br />
import org.eclipse.birt.report.model.api.RowHandle;<br />
import org.eclipse.birt.report.model.api.SessionHandle;<br />
import org.eclipse.birt.report.model.api.StructureFactory;<br />
import org.eclipse.birt.report.model.api.TableHandle;<br />
import org.eclipse.birt.report.model.api.activity.SemanticException;<br />
import org.eclipse.birt.report.model.api.elements.structures.ComputedColumn;<br />
<br />
import com.ibm.icu.util.ULocale;<br />
<br />
/**<br />
&nbsp;* Dynamic Table BIRT Design Engine API (DEAPI) demo.<br />
&nbsp;*/<br />
<br />
public class DECreateDynamicTable<br />
{<br />
&nbsp;&nbsp;&nbsp; ReportDesignHandle designHandle = null;<br />
&nbsp;&nbsp;&nbsp; ElementFactory designFactory = null;<br />
&nbsp;&nbsp;&nbsp; StructureFactory structFactory = null;&nbsp;&nbsp;&nbsp; <br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; public static void main( String[] args )<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DECreateDynamicTable de = new DECreateDynamicTable();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ArrayList al = new ArrayList();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; al.add(&quot;OFFICECODE&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; al.add(&quot;CITY&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; al.add(&quot;COUNTRY&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; de.buildReport(al, &quot;From Offices&quot; );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; catch ( IOException e )<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; catch ( SemanticException e )<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // TODO Auto-generated catch block<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; void buildDataSource( ) throws SemanticException<br />
&nbsp;&nbsp;&nbsp; {<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; OdaDataSourceHandle dsHandle = designFactory.newOdaDataSource(<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &quot;Data Source&quot;, &quot;org.eclipse.birt.report.data.oda.jdbc&quot; );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dsHandle.setProperty( &quot;odaDriverClass&quot;,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &quot;org.eclipse.birt.report.data.oda.sampledb.Driver&quot; );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dsHandle.setProperty( &quot;odaURL&quot;, &quot;jdbc:classicmodels:sampledb&quot; );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dsHandle.setProperty( &quot;odaUser&quot;, &quot;ClassicModels&quot; );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dsHandle.setProperty( &quot;odaPassword&quot;, &quot;&quot; );<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; designHandle.getDataSources( ).add( dsHandle );<br />
<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; void buildDataSet(ArrayList cols, String fromClause ) throws SemanticException<br />
&nbsp;&nbsp;&nbsp; {<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; OdaDataSetHandle dsHandle = designFactory.newOdaDataSet( &quot;ds&quot;,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &quot;org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet&quot; );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dsHandle.setDataSource( &quot;Data Source&quot; );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String qry = &quot;Select &quot;;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for( int i=0; i &lt; cols.size(); i++){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qry += &quot; &quot; + cols.get(i);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if( i != (cols.size() -1) ){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qry += &quot;,&quot;;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qry += &quot; &quot; + fromClause;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dsHandle.setQueryText( qry );<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; designHandle.getDataSets( ).add( dsHandle );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; void buildReport(ArrayList cols, String fromClause ) throws IOException, SemanticException<br />
&nbsp;&nbsp;&nbsp; {<br />
<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //Configure the Engine and start the Platform<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DesignConfig config = new DesignConfig( );<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; config.setProperty(&quot;BIRT_HOME&quot;, &quot;C:/birt-runtime-2_1_1/birt-runtime-2_1_1/ReportEngine&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; IDesignEngine engine = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try{<br />
<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Platform.startup( config );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; IDesignEngineFactory factory = (IDesignEngineFactory) Platform<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .createFactoryObject( IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; engine = factory.createDesignEngine( config );<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }catch( Exception ex){<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ex.printStackTrace();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SessionHandle session = engine.newSessionHandle( ULocale.ENGLISH ) ;<br />
<br />
&nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //open a design or a template<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; designHandle = session.openDesign(&quot;c:/tmp/testdeapi.rptdesign&quot;);<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; designFactory = designHandle.getElementFactory( );<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; buildDataSource();<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; buildDataSet(cols, fromClause);<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; TableHandle table = designFactory.newTableItem( &quot;table&quot;, cols.size() );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; table.setWidth( &quot;100%&quot; );<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; table.setDataSet( designHandle.findDataSet( &quot;ds&quot; ) );<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PropertyHandle computedSet = table.getColumnBindings( ); <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ComputedColumn&nbsp; cs1 = null;<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for( int i=0; i &lt; cols.size(); i++){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cs1 = StructureFactory.createComputedColumn();<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cs1.setName((String)cols.get(i));<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cs1.setExpression(&quot;dataSetRow[\&quot;&quot; + (String)cols.get(i) + &quot;\&quot;]&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; computedSet.addItem(cs1);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // table header<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RowHandle tableheader = (RowHandle) table.getHeader( ).get( 0 );<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for( int i=0; i &lt; cols.size(); i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; LabelHandle label1 = designFactory.newLabel( (String)cols.get(i) );&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; label1.setText((String)cols.get(i));<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; CellHandle cell = (CellHandle) tableheader.getCells( ).get( i );<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cell.getContent( ).add( label1 );<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // table detail<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RowHandle tabledetail = (RowHandle) table.getDetail( ).get( 0 );<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for( int i=0; i &lt; cols.size(); i++){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; CellHandle cell = (CellHandle) tabledetail.getCells( ).get( i );<br />
&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DataItemHandle data = designFactory.newDataItem( &quot;data_&quot;+(String)cols.get(i) );<br />
&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; data.setResultSetColumn( (String)cols.get(i));<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cell.getContent( ).add( data );<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; designHandle.getBody( ).add( table );<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Save the design and close it. <br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; designHandle.saveAs( &quot;c:/temp/sample.rptdesign&quot; ); //$NON-NLS-1$<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; designHandle.close( );<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println(&quot;Finished&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }catch (Exception e){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;}<br />
<br />
<br />
这个例子一共有四个函数 ：<br />
1 . Main 函数:&nbsp; 这个例子简单之处在与它可以直接的运行，只要你修改了<br />
&nbsp;&nbsp;&nbsp;&nbsp; config.setProperty(&quot;BIRT_HOME&quot;, &quot;C:/birt-runtime-2_1_1/birt-runtime-2_1_1/ReportEngine&quot;);&nbsp;&nbsp;&nbsp; 指向你自己的Birt Runtime 解压后的ReportEngine 目录.<br />
&nbsp;&nbsp;&nbsp;&nbsp; designHandle = session.openDesign(&quot;c:/tmp/testdeapi.rptdesign&quot;);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 你可以从Birt 里面建立一个新的Report template.然后指向这个report 就可以了<br />
&nbsp;&nbsp;&nbsp;&nbsp; designHandle.saveAs( &quot;c:/temp/sample.rptdesign&quot; ); //$NON-NLS-1$&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定一个你想保存的位置，c:/temp&nbsp; 目录存在你才能够保存到c:/temp 目录下.<br />
2 . buildDataSource&nbsp;&nbsp; 函数把一个ReportDesignHandle 的 Data Source 初始化, setProperties 左边的String 是不能变的，Data Source 的名字可以随便取，取DataSet 的时候要根据这个名字来取.<br />
3 . buildDataSet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过拼sql 的方式 ,来build DataSet, 注意sql 别拼错了.<br />
4 . buildReport&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意element 的初始化顺序.在所有的DataItem 外面都是一层Cell,Cell 外面才是row .这个例子使用的row 来拼成table 的，也可以用column 来拼，相对应的数据处理也是一个column 一个 column 的处理的了.<br />
<br />
</font>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/97412#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 03 Jul 2007 22:00:14 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/97412</link>
        <guid>http://jjjava.javaeye.com/blog/97412</guid>
      </item>
      <item>
        <title>BIRT (一) 安装BIRT</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/94855" style="color:red;">http://jjjava.javaeye.com/blog/94855</a>&nbsp;
          发表时间: 2007年06月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div align="center"><font size="4">商业智能(十八)    安装BIRT<br />
</font>
<div align="left"><font size="4">发现自己还上了javaeye的头版了，也算是灌水灌出了自己的特色了吧, 希望自己还是加紧时间学习，好为大家提供更多更好的优质纯净水.</font><br />
</div>
<font size="4"><br />
</font>
<div align="left"><font size="4">安装Birt 其实非常的简单.只需要下载Birt-Runtime-version 文件就可以了.下载解压后，其中有一个目录是ReportEngine 的目录，所有的Birt 能够运行都需要这个目录下的程序.<br />
另外一个就是WebViewerExample 目录，这是一个eclipse 的sample ,直接把它放到tomcat webapps目录下就可以了.<br />
运行成功后应该直接有 BIRT viewer has been installed 的提示,下面有个 View Example 的链接.它会调用一个Servlet 处理一个test.rptdesing 的模板并且接受一个默认的参数&ldquo;my parameter&quot; , <br />
你可以之后改变这个参数.<br />
test.rptdesign 文件在WebViewerExample 下面，另外还有一个test1.rptdesing 文件把你的浏览器指向<br />
<a href="http://localhost:8080/WebViewerExample/frameset?__report=test1.rptdesign" target="_blank">http://localhost:8080/WebViewerExample/frameset?__report=test1.rptdesign</a><br />
会弹出来一个parameter 对话框,随便输入两个1 ， 後然运行出来的报表是个非常简单的报表.<br />
这两个报表都是只用visual design 做出来的.算是最基本的入门了.<br />
<br />
再来看一下这个sample 的目录结构，在WebViewerExample下，有6个目录，一个index.jsp 文件和两个birt 模板文件.<br />
其中documents 目录，logs 目录 ， scriptlib 目录是在web.xml 里面定义的，你可以定义到其他地方,里面还有其他的定义，都有注释。<br />
在WEB-INF 目录下，有lib ， platform ,tlds 目录，web.xml文件 和 server-config.wsdd  ，这是一个标准的BIRT 安装目录，platform 下放的是从birt-runtime-version 的reportengine 下copy 过来的.<br />
另外还有一个viewer.properties 文件，里面定义了可以输出的文件格式，现在一共支持6种：html , pdf , postscript , doc , xls (也就是csv,或者说是excel） ,ppt<br />
如果你需要Birt 支持excel 或者 word 格式在这里定义就好了.<br />
# [EXTENSION SETTING]<br />
viewer.extension.html=html<br />
viewer.extension.pdf=pdf<br />
viewer.extension.postscript=ps<br />
viewer.extension.doc=doc<br />
viewer.extension.xls_prototype=xls<br />
viewer.extension.ppt=ppt<br />
<br />
# [OUTPUT FORMAT LABEL NAME]<br />
viewer.label.html=HTML<br />
viewer.label.pdf=PDF<br />
viewer.label.postscript=Postscript<br />
viewer.label.doc=Word<br />
viewer.label.xls_prototype=Excel<br />
viewer.label.ppt=Powerpoint<br />
<br />
# [CSV SEPARATOR]<br />
viewer.sep.0=,<br />
viewer.sep.1=;<br />
viewer.sep.2=:<br />
viewer.sep.3=|<br />
viewer.sep.4=\t<br />
<br />
后面的CSV SEPARATOR 是支持你导出数据用的.<br />
<br />
注意你的lib 都已经正确放置了先.<br />
<br />
下一篇是介绍用最简单的Design API 来设计一个模板.<br />
<br />
</font></div>
</div>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/94855#comments" style="color:red;">已有 <strong>3</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 27 Jun 2007 21:49:15 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/94855</link>
        <guid>http://jjjava.javaeye.com/blog/94855</guid>
      </item>
      <item>
        <title>eclipse europa 即将发布 birt 的新功能一览</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/91293" style="color:red;">http://jjjava.javaeye.com/blog/91293</a>&nbsp;
          发表时间: 2007年06月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font size="4">                        eclipse europa 即将发布 birt 的新功能一览<br />
最新的eclipse europa 即将在6月29号发布了.官方说会有21个项目同时发布.其中我只关心三个项目.一个是WTP , 一个是TPTP 最后一个是BIRT .<br />
我看了一下BIRT 所增加的新功能，从2.2M4 开始<br />
<a href="http://www.eclipse.org/birt/phoenix/project/notable2.2M4.php" target="_blank">http://www.eclipse.org/birt/phoenix/project/notable2.2M4.php</a><br />
<a href="http://www.eclipse.org/birt/phoenix/project/notable2.2M5.php" target="_blank">http://www.eclipse.org/birt/phoenix/project/notable2.2M5.php</a><br />
<a href="http://www.eclipse.org/birt/phoenix/project/notable2.2M6.php" target="_blank">http://www.eclipse.org/birt/phoenix/project/notable2.2M6.php</a><br />
<a href="http://www.eclipse.org/birt/phoenix/project/notable2.2RC0.php" target="_blank">http://www.eclipse.org/birt/phoenix/project/notable2.2RC0.php</a><br />
<br />
<br />
2.2 M4<br />
1 . 和WTP集成的BIRT Tag .<br />
2 . Word Emitter                     支持WORD 的 emitter . (emitter 翻译是发射，我想应该是可以预览和打印的输出格式吧)<br />
3 . XML Source Editor            支持xml 格式的编辑器<br />
4 . Property Editor Changes<br />
5 . Highlight Style                    对于特定条件的Item 进行高亮显示.<br />
<br />
2.2 M5<br />
1 . BIRT Chart Improvements             <br />
2 . Viewer Improvements<br />
3 . Emitters                            增强了PDF 的emitters<br />
4 . Advanced Properties        现在可以显示所有的属性了.<br />
<br />
2.2 M6<br />
1 . BIRT Chart Improvements     新增加了一种chart tag library 和chart view servlet<br />
2 . XLS Emitter Prototype           新增加了一种XLS 输出的格式<br />
3 . Linking Cascading Style Sheets      情理之中的事情<br />
4 . BIRT Viewer Changes        <br />
5 . Report Examples View           新提供了一些example,提供给初学者和想了解birt新功能的爱好者.<br />
6 . Dynamic Connection Profiles  动态的数据源链接<br />
7 . Report Parameter Changes    增加了一种组合框的parameter view.类似与选省份和城市的那种双选框.<br />
<br />
2.2 RC0<br />
1 . Web Service ODA               新增加的Web Service 的数据源.可以支持像ebay , amazon的那种Web Service 的数据了.<br />
2 . Charting Improvements       新增加使用script 来处理chart的事件.好像是用的javascript.<br />
3 . PPT Emitter                         新增加对Power Point  的emitter.<br />
4 . Dynamic Crosstab Support    <br />
这是最让我激动的功能.完全就是OLAP的功能的一部分.Palo的demo中，是通过一个Excel 的Plug-in,是excel 支持olap的，不过它不能跨平台，甚至连excel 都跨不出去，而birt提供的这个功能更加的强大.而且很容易就能够实现，定制化也比较强(就是说它提供API ，让你自己编程实现这些功能).<br />
<br />
一下子看到BIRT太多的功能了，希望能够正式发布的时候birt能够比较稳定吧.<br />
<br />
<br />
没有找到WTP2.0 和 TPTP 4.3 的新功能列表.<br />
其中我只关心在TPTP 4.2.2 Callisto 中的TPTP经常性的Block 的Issue 解决了没有.<br />
同样希望TPTP也能够稳定吧。功能倒是其次. java 中profiler 工具倒是不少，可是大多好的都是商业的，难得有一个这么好的开源的版本，要是bug问题不解决就不好了.<br />
<br />
听说eclipse 的SOA 建模工具第一次发布.我倒是不关心，目前还是把精力focus birt上了，觉得eclipse 本身可能已经没有太多新功能发展了，主要就是把plugin 做好，<br />
然后想办法能够解决plugin 之间版本的兼容性问题就够了. 最近也试用了一下NetBean ,没有深入用，还是有点失望的，希望NetBean 的坚定拥护者不要扁我. 字体丑，界面丑也就算了，但是跑出来吓人就是你的不对了嘛! 丑也就算了，速度也稍微慢一点（我说的是稍微）.本来想看一下它的Porfiler 功能怎么样的，后来还是算了，毕竟自己没打算用.就算是自己没有深入用过，不懂吧，乱说了话，希望不要引起Netbean 支持者的海扁.<br />
<br />
最近在collab下载svn 的时候无意中看到了它的svn enterprise 版的.其中有一个是支持eclipse 的 Mylyn 插件的（21个项目其中一个),做项目管理的.不知道eclipse 搞<br />
Mylyn 是不是有打算进入项目管理领域 . 它居然还是2.0版.不知道有哪位用过. <br />
<br />
最近使用firefox的时候 ，有时候打开一个网页莫名其妙的就firefox 挂掉了，也不是真的挂了，就是有时候等个2分钟它又好了，有时候firefox整个不见了，但是进程里面<br />
它还在，你点开一个新的firefox  然后两个人就手拉手的都跑出来了. 不知道是不是大家也有遇到过相同情况的. 装了Opera , firefox 挂掉的时候就用Opera , 里面有一个<br />
打电话的功能我觉得倒是非常的有意思，创意呀! 不希望firefox 独大 ， 也不希望eclipse 独大 ，更不希望Microsoft 独大 , 同样不希望 Intel 独大(AMD hold on) .<br />
有竞争才能推动发展嘛.<br />
<br />
最近在msn 上认识了许多朋友. 有一位跟我聊起了JBoss , 我对JBoss 的认识还停留在JBoss 服务器上.后来听他说才知道JBoss 已经发展了一套完整的J2EE 框架了，包括很多方面,才恍然大悟 原来现在中间件这么重要. Red Hat 跟exadel 结盟要推新的SOA 工具，好像SOA是很火的，不过还是认为如果公司不是做SOA 的，学SOA 没有什么用.SOA 要在中国成熟还要很多年的.那时候都不知道是个什么样子了.不过将来一个公司面对使用多种操作系统，多种数据库，多种软件平台，多种编程语言，总会需要一个框架来解决这些问题的，就算SOA 成功了也好，SOA 失败了也好，需求总是会有的.还是等SOA 成熟了再观望一下吧, 广告看看还可以，要真掏钱出来还是要谨慎的。<br />
纯属个人认识，说的不对还请.<br />
<br />
写的比较杂,就当是看八卦吧.<br />
<br />
最近学习Birt ，主要是它的新功能.然后还是准备学会如何在pentaho里面集成 birt 吧.希望能够和birt 爱好者，尤其是高手一起交流.<br />
<br />
</font>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/91293#comments" style="color:red;">已有 <strong>14</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 17 Jun 2007 16:28:15 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/91293</link>
        <guid>http://jjjava.javaeye.com/blog/91293</guid>
      </item>
      <item>
        <title>商业智能研究(十七) Mondrian 如何使用 materialized view</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/88948" style="color:red;">http://jjjava.javaeye.com/blog/88948</a>&nbsp;
          发表时间: 2007年06月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div align="center"><font size="4">商业智能研究(十七)     Mondrian 如何使用 materialized view</font><br />
</div>
<font size="4"><br />
在第十四篇文章中，我把所有关于 agg 开头的表全部都重命名了，所以才得到了我后面要分析的sql ,如果没有把agg 开头的表重命名的话，得到的sql 是不一样的 :<br />
select &quot;agg_c_10_sales_fact_1997&quot;.&quot;the_year&quot; as &quot;c0&quot;, <br />
sum(&quot;agg_c_10_sales_fact_1997&quot;.&quot;store_sales&quot;) as &quot;m0&quot;, <br />
sum(&quot;agg_c_10_sales_fact_1997&quot;.&quot;store_cost&quot;) as &quot;m1&quot; <br />
from   &quot;agg_c_10_sales_fact_1997&quot; &quot;agg_c_10_sales_fact_1997&quot; <br />
where  &quot;agg_c_10_sales_fact_1997&quot;.&quot;the_year&quot; = 1997 <br />
group by &quot;agg_c_10_sales_fact_1997&quot;.&quot;the_year&quot;;<br />
<br />
你会发现很多的数据都是从 agg 开头的表中取来的. 列出其中的 &quot;agg_pl_01_sales_fact_1997&quot; table 是怎样填数据的，这个脚本是从命令行执行java 语句的时候在最后一段，从命令行copy出来的.<br />
INSERT INTO &quot;agg_pl_01_sales_fact_1997&quot; <br />
(&quot;product_id&quot;, &quot;time_id&quot;, &quot;customer_id&quot;, &quot;store_sales_sum&quot;,<br />
&quot;store_cost_sum&quot;, &quot;unit_sales_sum&quot;, &quot;fact_count&quot;)<br />
SELECT   &quot;product_id&quot; AS &quot;product_id&quot;, &quot;time_id&quot; AS &quot;time_id&quot;,<br />
&quot;customer_id&quot; AS &quot;customer_id&quot;,<br />
SUM (&quot;store_sales&quot;) AS &quot;store_sales&quot;,<br />
SUM (&quot;store_cost&quot;) AS &quot;store_cost&quot;,<br />
SUM (&quot;unit_sales&quot;) AS &quot;unit_sales&quot;, COUNT (*) AS fact_count<br />
FROM   &quot;sales_fact_1997&quot;<br />
GROUP BY  &quot;product_id&quot;, &quot;time_id&quot;, &quot;customer_id&quot;<br />
<br />
这个 agg 开头的表就相当于是materialized view 了，只不过不是所有数据库都有materialized view ，所以就用不同的table 来存储数据.<br />
当我们把 agg 开头的表重命名以后，mondrian 就找不到了，所以才会直接去相应的表里面取数据，这个定义是在mondrian 里面的 foodmart.xml 文件里面定义的.在WEB-INF/queries 下面.<br />
这种表叫做 aggregate 表 ,也就是可以用这种表来强制mondrian 使用我们的materialized view , mondrian 官方推荐使用materialized view 建立这种 aggregate 表，你可以看到在Cube 元素，有关这些表的定义.<br />
所以我们定义的materialized view 可以直接在foodmart.xml 里面定义.关于如何建立mondrian 的 schema 文件，可以参考mondrian 的官方主页，里面写的很详尽了 . <br />
如果你要写mondrian 的 schema 文件，建议使用mondrian 里面的workbench ,这个软件是jaspersoft 里面的一个人写的. pentaho 官方的那个cube desinger 我根本就打不开，不知道是不是什么配置问题.<br />
<br />
<br />
6月7号 收到了pentaho community 的邮件，因为我参加了他们的beta programmer .新的1.6 release 马上就要发布了，其中提到了6个新的特性.<br />
1 . Web-based Ad Hoc Query and Reporting  <br />
2 . Pentaho Metadata        <br />
3 . Security<br />
4 . Subscriptions             一个基于时间调度的计划任务.1.5.2 才加入的新特性，使用户更容易得到自己想要的信息.算是pentaho KPI 的一种实现手段.<br />
5 . RDBMS repository<br />
6 . Mondrian Schema and Data cache flushing <br />
<br />
你可以看到其中的 1-5 都是跟metadata 有关的，可见metadata 的 管理对于商业智能也是越来越重要了.<br />
由于我可能会抽出一定时间参与pentaho 1.6 的测试工作，所以更新Blog 的速度会慢下来.当然，等全部的工作做完了，我还是会写几篇关于参与pentaho 测试的文章的，也欢迎大家与我讨论pentaho 的问题,<br />
我会加所以给我留言的朋友为好友，并跟他们交换msn . 希望能和喜欢商业智能，开源软件的朋友一起共同进步.<br />
</font><font size="4"><br />
<br />
<br />
</font><font size="4"> <br />
</font>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/88948#comments" style="color:red;">已有 <strong>1</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 10 Jun 2007 18:48:15 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/88948</link>
        <guid>http://jjjava.javaeye.com/blog/88948</guid>
      </item>
      <item>
        <title>商业智能研究(十六)materialized view+dimension提高mondrian性能</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/88947" style="color:red;">http://jjjava.javaeye.com/blog/88947</a>&nbsp;
          发表时间: 2007年06月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font size="4">商业智能研究(十六)    用materialized view + dimension 来提高mondrian 的性能(二)<br />
<br />
接着上一篇的定义我们定义如下两个dimension :<br />
CREATE DIMENSION PRODUCT_DIM<br />
LEVEL &quot;product_id&quot;              IS  &quot;product&quot;.&quot;product_id&quot;<br />
LEVEL &quot;brand_name&quot;              IS  &quot;product&quot;.&quot;brand_name&quot;<br />
LEVEL &quot;product_class_id&quot;        IS  &quot;product_class&quot;.&quot;product_class_id&quot;     <br />
LEVEL &quot;product_category&quot;        IS  &quot;product_class&quot;.&quot;product_category&quot;<br />
LEVEL &quot;product_department&quot;      IS  &quot;product_class&quot;.&quot;product_department&quot;<br />
LEVEL &quot;product_family&quot;          IS  &quot;product_class&quot;.&quot;product_family&quot;<br />
HIERARCHY PRODUCT_ROLLUP  (<br />
&quot;product_id&quot;               CHILD OF<br />
&quot;brand_name&quot;               CHILD OF<br />
&quot;product_class_id&quot;         CHILD OF<br />
&quot;product_category&quot;         CHILD OF<br />
&quot;product_department&quot;       CHILD OF<br />
&quot;product_family&quot; <br />
JOIN KEY (&quot;product&quot;.&quot;product_class_id&quot;) REFERENCES &quot;product_class_id&quot;<br />
)<br />
ATTRIBUTE &quot;product_id&quot; DETERMINES (&quot;product_name&quot;)<br />
ATTRIBUTE &quot;product_class_id&quot; DETERMINES (&quot;product_subcategory&quot;);<br />
<br />
<br />
CREATE DIMENSION TIME_DIM <br />
LEVEL time       IS  &quot;time_by_day&quot;.&quot;time_id&quot;<br />
LEVEL month      IS  &quot;time_by_day&quot;.&quot;month_of_year&quot;<br />
LEVEL quarter    IS  &quot;time_by_day&quot;.&quot;quarter&quot;<br />
LEVEL year       IS  &quot;time_by_day&quot;.&quot;the_year&quot;<br />
HIERARCHY TIME_ROLLUP  (<br />
time            CHILD OF<br />
month           CHILD OF<br />
quarter         CHILD OF<br />
year        <br />
)<br />
ATTRIBUTE time DETERMINES (&quot;time_by_day&quot;.&quot;the_date&quot;);<br />
<br />
然后我们建立materialized view , 注意QUERY_REWRITE_INTEGRITY 和 QUERY_REWRITE_ENABLED 应该已经正确的设置了.<br />
CREATE MATERIALIZED VIEW PRODUCT_SUM<br />
BUILD IMMEDIATE<br />
REFRESH ON DEMAND<br />
ENABLE QUERY REWRITE<br />
AS<br />
SELECT &quot;time_by_day&quot;.&quot;time_id&quot; ,<br />
&quot;product&quot;.&quot;product_id&quot;,<br />
&quot;product_class&quot;.&quot;product_class_id&quot; ,<br />
SUM(&quot;sales_fact_1997&quot;.&quot;store_sales&quot;) ,<br />
SUM(&quot;sales_fact_1997&quot;.&quot;store_cost&quot;)<br />
FROM &quot;time_by_day&quot; &quot;time_by_day&quot;,<br />
&quot;product&quot; &quot;product&quot; ,<br />
&quot;product_class&quot; &quot;product_class&quot; ,<br />
&quot;sales_fact_1997&quot; &quot;sales_fact_1997&quot;<br />
WHERE &quot;sales_fact_1997&quot;.&quot;time_id&quot; = &quot;time_by_day&quot;.&quot;time_id&quot;<br />
AND &quot;sales_fact_1997&quot;.&quot;product_id&quot; = &quot;product&quot;.&quot;product_id&quot;<br />
AND &quot;product&quot;.&quot;product_class_id&quot; = &quot;product_class&quot;.&quot;product_class_id&quot;<br />
GROUP BY &quot;time_by_day&quot;.&quot;time_id&quot;,<br />
&quot;product&quot;.&quot;product_id&quot; ,<br />
&quot;product_class&quot;.&quot;product_class_id&quot;;<br />
<br />
现在我们 set autotrace on .<br />
<br />
执行<br />
SELECT &quot;time_by_day&quot;.&quot;the_date&quot; ,  <br />
&quot;product_class&quot;.&quot;product_family&quot; ,<br />
SUM(&quot;sales_fact_1997&quot;.&quot;store_sales&quot;) ,<br />
SUM(&quot;sales_fact_1997&quot;.&quot;store_cost&quot;)<br />
FROM &quot;time_by_day&quot; &quot;time_by_day&quot;,<br />
&quot;product&quot; &quot;product&quot; ,<br />
&quot;product_class&quot; &quot;product_class&quot; ,<br />
&quot;sales_fact_1997&quot; &quot;sales_fact_1997&quot;<br />
WHERE &quot;sales_fact_1997&quot;.&quot;time_id&quot; = &quot;time_by_day&quot;.&quot;time_id&quot;<br />
AND &quot;sales_fact_1997&quot;.&quot;product_id&quot; = &quot;product&quot;.&quot;product_id&quot;<br />
AND &quot;product&quot;.&quot;product_class_id&quot; = &quot;product_class&quot;.&quot;product_class_id&quot;<br />
GROUP BY &quot;time_by_day&quot;.&quot;the_date&quot;,  <br />
&quot;product_class&quot;.&quot;product_family&quot;;<br />
<br />
从图一中我们看到，当我们把product 聚合到了最高的level product_family,oracle 的 执行计划是从product_sum 中来做聚合的.这就是因为我们建立的dimension 告诉了oracle product有这种层次的关系.product的dimension 即告诉了product_id 能够决定product_name，也告诉了product_id能够聚合product_family , 同样的我们把Time 聚合到最高的level <br />
SELECT &quot;time_by_day&quot;.&quot;the_year&quot; ,  <br />
&quot;product&quot;.&quot;product_name&quot; ,<br />
SUM(&quot;sales_fact_1997&quot;.&quot;store_sales&quot;) ,<br />
SUM(&quot;sales_fact_1997&quot;.&quot;store_cost&quot;)<br />
FROM &quot;time_by_day&quot; &quot;time_by_day&quot;,<br />
&quot;product&quot; &quot;product&quot; ,<br />
&quot;product_class&quot; &quot;product_class&quot; ,<br />
&quot;sales_fact_1997&quot; &quot;sales_fact_1997&quot;<br />
WHERE &quot;sales_fact_1997&quot;.&quot;time_id&quot; = &quot;time_by_day&quot;.&quot;time_id&quot;<br />
AND &quot;sales_fact_1997&quot;.&quot;product_id&quot; = &quot;product&quot;.&quot;product_id&quot;<br />
AND &quot;product&quot;.&quot;product_class_id&quot; = &quot;product_class&quot;.&quot;product_class_id&quot;<br />
GROUP BY &quot;time_by_day&quot;.&quot;the_year&quot;,  <br />
&quot;product&quot;.&quot;product_name&quot;;<br />
从图二中的执行计划同样可以看出我们只选取Time 来做聚合的时候，oracle 仍然是从product_sum 表中来做聚合, 用time_id 来决定the_date ,time_id同样可以聚合year.<br />
<br />
最后一个是同时聚合product 和 time <br />
SELECT &quot;time_by_day&quot;.&quot;the_year&quot; ,  <br />
&quot;product_class&quot;.&quot;product_family&quot; ,<br />
SUM(&quot;sales_fact_1997&quot;.&quot;store_sales&quot;) ,<br />
SUM(&quot;sales_fact_1997&quot;.&quot;store_cost&quot;)<br />
FROM &quot;time_by_day&quot; &quot;time_by_day&quot;,<br />
&quot;product&quot; &quot;product&quot; ,<br />
&quot;product_class&quot; &quot;product_class&quot; ,<br />
&quot;sales_fact_1997&quot; &quot;sales_fact_1997&quot;<br />
WHERE &quot;sales_fact_1997&quot;.&quot;time_id&quot; = &quot;time_by_day&quot;.&quot;time_id&quot;<br />
AND &quot;sales_fact_1997&quot;.&quot;product_id&quot; = &quot;product&quot;.&quot;product_id&quot;<br />
AND &quot;product&quot;.&quot;product_class_id&quot; = &quot;product_class&quot;.&quot;product_class_id&quot;<br />
GROUP BY &quot;time_by_day&quot;.&quot;the_year&quot;,  <br />
&quot;product_class&quot;.&quot;product_family&quot;;<br />
同样的，oracle 还是从product_sum 中取数据 .<br />
<br />
<br />
因为materialized view 的使用，我们可以把我们要分析的Cube 作成一个或几个非常大的materialized view , 建立正确的dimension 之后，当你查询的时候,由于数据已经提前计算过了，所以查询的速度比较快，在加上dimension可以告诉oracle 数据之间的层级关系，减少了我们建立不必要的materialized view , 所以使数据能够得到更加充分的利用.<br />
关于如何建立dimension 倒是比较简单，只要你弄懂数据之间的层级关系就可以了.<br />
对于如何建立materialized view 倒是比较麻烦，<br />
我举个简单的例子吧:<br />
在mondrian 的 foodmart 的例子中，我们可以任意的选取 指标 , product , customers , education leve , gender ,marital sttus ,promotin media ,promotions , store , store size in SQFT , store type , time , yearly income 这十三个要分析的数据来建立cube ,用户有可能使用product 来做分析的维度，也有可能把product 来做Measure 或者不选，所以我们不可能建立所有情况考虑到的Cube .<br />
ps : 如果你非要搞一个出来的话，我可以给你点提示<br />
总的方案有2 的 13 次方：8096 种方案.也就是你要建立8096 个materialized view 就可以解决所有情况.<br />
C 13 3 ： 数学里面的概率问题， 十三个里面选3个出来，不论顺序的. C 13 3 = 13*12*12/(1*2*3)<br />
代表的意思是从13个里面选3个出来做fact table ,其余十个做dimension .不论你选不选这些dimension 都一样，<br />
总的方案 = c 13 1 + c 13 2 + c 13 3 + ...... + c 13 13 = 2 的十三次方 = 8096.<br />
<br />
如何建立materialized view 还是主要是看你如何建立你的分析的维度.如果你的fact table 本身很多.而维度也很多的情况下，不可能每个fact table 都建立一个关于所有dimension 的materialized view ,对于我们的product dimension数据还算是比较少的，如果达到像大型超市那么多的产品，可能还需要在brand_name 或者 subcategory 来建立materialized view ,所以还是建议根据用户的查询sql 来分析用户到底经常查询那些数据.<br />
<br />
下一篇继续介绍 Mondrian 如何使用materialized view 来提高性能.<br />
<br />
图一 :     product 集合到最高层 的 执行计划.<br />
<img src="http://jjjava.javaeye.com/upload/picture/pic/3776/606f9936-fd5d-459c-a0c7-b8621015f20d.png" alt="" /><br />
<br />
<br />
图二 :  Time 聚合到最高层 的执行计划<br />
<img src="http://jjjava.javaeye.com/upload/picture/pic/3777/335a8863-2218-466a-822b-82274b91540e.png" alt="" /><br />
<br />
图三 ： 同时将Time 和 product 聚合到最高层 的执行计划<br />
<img src="http://jjjava.javaeye.com/upload/picture/pic/3778/78b51bf1-baa4-42c4-9b65-3f27ae088927.png" alt="" /><br />
<br />
图四 :  drill down product 的样子<br />
<img src="http://jjjava.javaeye.com/upload/picture/pic/3779/e0d92297-d7f6-48a4-bfca-647782047ce9.png" alt="" /><br />
<br />
图五 ： 十三种数据，到底怎样建materialized view 呢 ?<br />
<img src="http://jjjava.javaeye.com/upload/picture/pic/3780/b32283cd-1a4c-454c-bdd6-7422a93f5a42.png" alt="" /><br />
<br />
</font><font size="4"><br />
<font size="4"><br />
<br />
</font></font>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/88947#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 10 Jun 2007 18:44:32 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/88947</link>
        <guid>http://jjjava.javaeye.com/blog/88947</guid>
      </item>
      <item>
        <title>商业智能研究(十五) materialized view+dimension提高mondrian性能</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/88946" style="color:red;">http://jjjava.javaeye.com/blog/88946</a>&nbsp;
          发表时间: 2007年06月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div align="center"><font size="4">materialized view+dimension提高mondrian性能<br />
</font>
<div align="left"><font size="4">按着上一篇的步骤部署好了mondrian 之后<br />
进入数据库,修改所有以agg开头的表格，把它们重命名或者或者drop掉，下一篇我会解释为什么的.<br />
<br />
修改 WEB-INF / mondrian.properties 文件，加上如下两个key<br />
mondrian.trace.level=1<br />
mondrian.debug.out.file=e:/mondrianfoodmart.log<br />
然后把mondrian.properties文件copy 到tomcat  的 bin 目录下重新启动tomcat.<br />
<br />
打开浏览器进入JPivot with arrows 的example .<br />
一直drill down product. All Products -&gt; Drink -&gt; Alcoholic Beverages -&gt; Beer and Wine -&gt; Beer -&gt; Good -&gt; Good Imported Beer<br />
<br />
你会在e:/ 下找到一个mondrianfoodmart.log 的文件，打开这个文件，你会看到类似与下面的语句 :<br />
SqlMemberSource.getMemberChildren: executing sql [select &quot;time_by_day&quot;.&quot;the_year&quot; as &quot;c0&quot; from &quot;time_by_day&quot; &quot;time_by_day&quot; group by &quot;time_by_day&quot;.&quot;the_year&quot; order by &quot;time_by_day&quot;.&quot;the_year&quot; ASC], exec 31 ms, exec+fetch 31 ms, 2 rows<br />
你可以把这个文件copy一份到其他地方，我们就是要分析这个文件，来知道mondrian到底执行了那些sql语句.<br />
<br />
它的语法格式大概如下:<br />
**** executing sql [ 执行的sql ]  exec 时间 ， exec + fetch  时间 ， 取得的数据行数.<br />
其中前面的**** 部分是看你执行的那些操作，<br />
mondrian 做drill down 的时候一般执行3 个 sql ,<br />
<br />
1 . 取得左边的dimension 的一个层次结构下的子元素的数目.比如All Products 下就有三个: Drink , Food , Non-Consumable <br />
一般通过如下sql取得 : <br />
SELECT COUNT(DISTINCT &quot;product_class&quot;.&quot;product_family&quot;) AS &quot;c0&quot; FROM &quot;product_class&quot; &quot;product_class&quot;;<br />
<br />
<br />
2 . 取得dimension 子元素的名称 : 象如下sql :<br />
SELECT &quot;product_class&quot;.&quot;product_department&quot; AS &quot;c0&quot;<br />
FROM &quot;product&quot; &quot;product&quot;,  &quot;product_class&quot; &quot;product_class&quot;<br />
WHERE &quot;product&quot;.&quot;product_class_id&quot; = &quot;product_class&quot;.&quot;product_class_id&quot;<br />
AND &quot;product_class&quot;.&quot;product_family&quot; = 'Drink'<br />
GROUP BY &quot;product_class&quot;.&quot;product_department&quot;<br />
ORDER BY &quot;product_class&quot;.&quot;product_department&quot; ASC;<br />
<br />
<br />
3 . 取得对应dimension的实际数据 , 象如下sql：<br />
SELECT &quot;time_by_day&quot;.&quot;the_year&quot; AS &quot;c0&quot;,   &quot;product_class&quot;.&quot;product_family&quot; AS &quot;c1&quot;,<br />
SUM(&quot;sales_fact_1997&quot;.&quot;store_sales&quot;) AS &quot;m0&quot;,  SUM(&quot;sales_fact_1997&quot;.&quot;store_cost&quot;) AS &quot;m1&quot;<br />
FROM &quot;time_by_day&quot; &quot;time_by_day&quot;,  &quot;sales_fact_1997&quot; &quot;sales_fact_1997&quot;,  &quot;product_class&quot; &quot;product_class&quot;,<br />
&quot;product&quot; &quot;product&quot;<br />
WHERE &quot;sales_fact_1997&quot;.&quot;time_id&quot; = &quot;time_by_day&quot;.&quot;time_id&quot;<br />
AND &quot;time_by_day&quot;.&quot;the_year&quot; = 1997<br />
AND &quot;sales_fact_1997&quot;.&quot;product_id&quot; = &quot;product&quot;.&quot;product_id&quot;<br />
AND &quot;product&quot;.&quot;product_class_id&quot; = &quot;product_class&quot;.&quot;product_class_id&quot;<br />
GROUP BY &quot;time_by_day&quot;.&quot;the_year&quot;,<br />
&quot;product_class&quot;.&quot;product_family&quot;;<br />
<br />
<br />
打开你的文本编辑器，我用的是vi , 执行两个替换命令<br />
1 .         :%s/^.*executing sql \[//g<br />
2 .         :%s/\], exec.*$/;/g<br />
第一个命令是将所有' executing sql [ '之前的字符串去掉，第二个命令是将所有 ' ] exec ' 之后的字符串换成 ; <br />
这个时候就只剩下可以执行的sql 了.把里面的内容copy 到你的sql 编辑器里面，我用的是oracle 官方的sql developer , 把它format一下，然后依次执行一下里面的所有sql ,看一下结果.<br />
<br />
通过研究这个结果，我们可以确定product 的层次关系:<br />
1 . 在product表里面，没有使用联合主键来确定product的唯一性，而是使用 product_id 作为主键，其中product_name 也是唯一的，对应 : Good Imported Beer , Good Light Beer .<br />
2 .  product_name 上一级是brand_name ，对应  : Good , Pearl ,Portsmounth , Top Measure , Walrus<br />
3 .  brand_name 的上一级是subcategory ,它在product_class表里面，product 和 product_class 通过product_class_id 链接起来，同样的，product_class 表没有用联合主键来定义唯一性，而是用product_class_id 来做主键，其中product_subcategory 是唯一的，跟product_class_id 是一一对应的. subcategory 有：Beer , Wine <br />
4 . product_subcategory的上一级是category ，对应 : Beer and Wine .<br />
5 . category的上一级是department , 对应 : Alcoholic Beverages , Beverages , Dairy . <br />
6 . department的上一级是family ,也是最顶级了 , 对应 : Drink , Food ,Non-Consumable .<br />
<br />
在我的例子中，我将使用Time 和 Product 来做Dimension ， 应为他们比较有代表性，<br />
time_by_day 表中，有十个column ,最后一个 fiscal_period 没有用.<br />
1 . time_id  这个表中的主键<br />
2 . the_date 数据类型是timestamp,是唯一的,其中定义了从1997年1月1日开始到1998年12月31日的所有日期.<br />
3 . the_day  定义的星期,比如 Monday .<br />
4 . the_month 定义的月份，比如September <br />
5 . the_year  年份 ， 1997 和 1998 .<br />
6 . day_of_month 月份中的日期， 比如23代表那个月份的23号 .<br />
7 . week_of_year 一年中的第几个星期，比如40 代表一年中的第40个星期<br />
8 . month_of_year 一年中的第几个月，比如9 代表第九个月，<br />
9 .  quarter , 季度 .<br />
Time dimension 建立在time_by_day 表上，其中可以用多个层级来表示Time的level 关系，比如the_year -&gt; quarter -&gt; the_month -&gt; the_date ,或者year -&gt; week_of_year -&gt; the_day -&gt; the_date .<br />
<br />
Product Dimension 建立在product 和 product_class 表上，是跨表的dimension<br />
product.product_id 主键<br />
product.product_name  最低的level .<br />
product.brand_name    第二level . <br />
product.product_class_id 映射到product_class 的外键<br />
product 其他colun 都是非主属性了.<br />
product_class.product_class_id   主键<br />
product_class.product_subcategory  唯一的，对应product_class_id   第三level.<br />
product_class.product_category    第四level.<br />
product.product_department        第五level.<br />
product.product_family            第六level.<br />
<br />
下篇接着写dimension + materialized view .<br />
</font><font size="4"><br />
</font></div>
</div>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/88946#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 10 Jun 2007 18:34:36 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/88946</link>
        <guid>http://jjjava.javaeye.com/blog/88946</guid>
      </item>
      <item>
        <title>商业智能研究(十四)   mondrian + oracle 部署foodmart demo</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/88945" style="color:red;">http://jjjava.javaeye.com/blog/88945</a>&nbsp;
          发表时间: 2007年06月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div align="center"><font size="4">mondrian + oracle 部署foodmart demo</font><br />
</div>
<font size="4">mondrian作为开源世界的OLAP 服务器,还是比较成熟的,本文将介绍如何在在mondrian 上部署它自己提供的foodmart demo 来向大家展示mondrian 在oracle 上如何做OLAP服务器.<br />
<br />
1 . 首先，下载mondrian的源文件(不是derby的那一个) .<br />
2 . 把解压缩后的lib / mondrian.war 文件copy 到tomcat 的webapps 文件夹下.让它自动解压.<br />
3 . 打开命令行，进入mondrian 的 lib 目录， 执行以下命令，<br />
java -cp &quot;mondrian.jar;log4j-1.2.9.jar;eigenbase-resgen.jar;eigenbase-xom.jar;ojdbc14.jar;eigenbase-properties.jar&quot; <br />
mondrian.test.loader.MondrianFoodMartLoader  <br />
-verbose  -tables -data -jdbcDrivers=&quot;oracle.jdbc.driver.OracleDriver&quot; <br />
-inputFile=FoodMartCreateData.sql    <br />
-outputJdbcURL=&quot;jdbc:oracle:thin:dbusername/dbpassword@oracle_host:1521:dbname&quot;<br />
注意mondrian需要oracle 的ojdbc14驱动，不是class12.jar  ,它在oracle_home/jdbc/lib/ojdbc.jar 文件夹下，如果没有可以到oracle官方网站去下.地址是http://download.oracle.com/otn/utilities_drivers/jdbc/9201/ojdbc14.jar<br />
其中inputFile的位置指定到你FoodMartCreateData.sql 的位置，我是已经把它放到了lib 目录下.<br />
详细的参数可以到http://mondrian.pentaho.org/documentation/installation.php 看看.<br />
4 . 这个时候你的数据库已经建立好了，其中每一个table都是有数据的. 注意所有的table 和 column 都是用双引号括起来的.<br />
5 . 修改WEB-INF / mondrian.properties 和 DataSource.xml 文件 , 指定其中的数据源.<br />
Provider=mondrian;<br />
Jdbc=jdbc:oracle:thin:<user_name>/
<password>@//<host_name>:
<port>/<db_name>;<br />
JdbcDrivers=oracle.jdbc.OracleDriver;<br />
Catalog=/WEB-INF/queries/FoodMart.xml;<br />
你的jdbc驱动应该已经copy到lib目录下了，把其中的&lt; &gt;内的替换成自己的数据源.<br />
6 . 修改WEB-INF / queries 下的arrows.jsp , colors.jsp , fourhier.jsp , mondrian.jsp , testquery.jsp 文件中的数据源部分，跟mondrian.properties文件是一样的.<br />
7 .这个时候打开你的tomcat , 让浏览器指向localhost:8080/mondrian ，你可以看到有8个 mondrian 的example ,其中最下面两个好像不能进，报ODBC错误，可能还需要其他地方的配置，其余都是可以进的.<br />
<br />
</db_name></port>
</host_name></password>
</user_name></font><font size="4"><br />
<font size="4"><br />
</font></font>
          <br/><br/>
          <span style="color:red;">
            <a href="http://jjjava.javaeye.com/blog/88945#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 10 Jun 2007 18:32:23 +0800</pubDate>
        <link>http://jjjava.javaeye.com/blog/88945</link>
        <guid>http://jjjava.javaeye.com/blog/88945</guid>
      </item>
      <item>
        <title>商业智能研究 (十三)  oracle warehouse 一些基本概念</title>
        <author>jjjava</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jjjava.javaeye.com">jjjava</a>&nbsp;
          链接：<a href="http://jjjava.javaeye.com/blog/88691" style="color:red;">http://jjjava.javaeye.com/blog/88691</a>&nbsp;
          发表时间: 2007年06月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div align="center"><font size="4">oracle warehouse 一些基本概念</font><br />
</div>
<font size="4">先介绍一些基本的概念，为了后面介绍如何在oracle上使用materialized view + dimension 部署foodmart demo 的例子的时候做些背景介绍。<br />
<br />
数据仓库不同与普通的OLTP 数据模型，它由两种表组成:事实表(Fact table) , 维度表(Dimension Table)<br />
<br />
Fact table : Fact table 主要储存用户实际感兴趣的信息的表 . 事实表有多个维表的外键 , 事实表的主属性可以定义成多个外键的集合 . 事实表的从属性称为事实（Fact）或者叫度量(Measure) ，它们一般都是数值或其他可以进行计算的数据.<br />
<br />
Dimension table : Dimension table 就是我们需要分析的主题了，它主要表现层次结构，分类信息，比如Time,Product,<br />
Customer,location ,dimension table 有时候又叫做lookup 或reference 表,dimension table  一般随ETL过程缓慢的变化而变化的.它一般比较小，但是却决定了数据库的性能，因为我们要在fact table 和dimension table 做多种join 操作.<br />
<br />
Star Schemas<br />
星形模型之所以被称作星形模型是因为它是由中心的一个或者多个事实表周围围绕一组维表组成。<br />
<img src="http://jjjava.javaeye.com/upload/picture/pic/3768/f2efac8e-4ff2-47ec-9c4e-8ff9e2e0a1a6.png" alt="" /><br />
<br />
<br />
materialized view<br />
在oracle中，materialized view 是一个预先计算的，从fact table 和dimension table 做的聚合操作(不一定只有sum操作)，view 是不储存数据的，但是materialized view 是存储数据的，它是oracle构建数据仓库最重要的技术之一，主要是为了解决性能的问题，就象MOLAP 系统预先计算的cube 是一样的.<br />
<br />
dimension<br />
dimension 是建立在dimension table 是上的，它只是一个概念的定义，主要定义level,category 的信息，它实际并不存储任何的数据，数据仍然是在dimension table中的，dimension 主要是为了配合materialized view 来解释数据的层次关系，也是为了解决性能问题的.<br />
<br />
为了在oracle中使用materialized view ,用户必须有create materialized view 的权限.<br />
为了使materialized viwe 发挥作用，两个参数必须先定义：<br />
QUERY_REWRITE_ENABLED=TRUE;<br />
QUERY_REWRITE_INTEGRITY=TRUSTED;<br />
materialized view 主要可以减少物理的读写次数，减少CPU的计算时间，提高响应速度.但