发布新日志

  • Birt 开发小结

    2009-09-30 16:54:49

    最近不务正业,跑去帮忙做Birt报表开发了,好久没有做开发了,碰了不少钉子。嘛,有时换换感觉也不错,不过可惜,做完这次我想也不会有什么机会再碰了,我把一些开发时的心得什么的写一下,也算是纪念吧。


    1. 要使用dataset的字段,或者 report parameter,都要在页面建立binding(比如把字段拖放到layout上一次),而不需要参数留在layout上(比如建立binding后在layout上删除参数也无妨)

    2. 一个dataset,只能和页面上的一个table 一一对应,如果需要report能够多段显示(比如先显示一些数据,然后点击其中一个链接或者按钮,再显示另外的内容)可以考虑用多个dataset。

    3. 一般可以放在layout上面做的事:

    String,data time,number 的格式
    grouping
    sorting

    鉴于我们通常是写sql从数据库拿数据,然后放入dataset,在布局在页面上,上面这几项工作,也可以在sql里面完成,不过为了简化sql,可以把这几种操作通过报表的设置来做,至于那种效率高,我就不知道了哈。

    PS:有时也会混用的,比如sql中用sum等函数统计某类数据的总值,然后在页面上分组,再统计总数。那种方便就用那种吧(这句话好废...)


    4. grouping 里面不支持group by多个参数,不过把参数用加号连接起来作为group on的条件就行了


    5. 如果客户可能会在报表做好之后,在使用时临时加入一些查询条件,可以在report parameter里面定义一个参数(比如叫where)并设置成可见,默认值为1=1,然后加入到你的sql的where子句的最后,那么想临时增加查询条件的时候,就可以通过修改where的值来实现而无须修改报表。

    PS:以上做法用于报表是在maximo界面上生成报表,在业务系统里面触发就不行了。不过还是有些用处的,起码提供了一点点扩展性和自由度。

    6. birt的开发环境有一点不太友好,有时preview等运行时出错,没有很明确报告错误(特别是组装sql的时候更是),这时可以加上以下语句,直接输出想输出的数据来debug

    importPackage( Packages.java.io);
    out = new PrintWriter( new FileWriter( "d:/events.txt", true ) );
    out.println( sqlText);
    out.close();

    适用于dataset,layout中的控件的各种方法,还有能够使用Expression Builder的地方

    7. birt的各部分的运行顺序

    我在dataset,layout控件,report的各个方法中加入debug code,试了才知道,运行顺序和想象中的不同。

    // report 自身的方法
    initialize()

    // 运行设置在layout上控件的处理方法
    onPrepare()
    onPrepare()

    // data set 的方法,取数据,把数据塞入dataset的变量中
    beforeOpen()
    describe()
    open()
    fetch()

    // 设定layout中的属性,比如 visibility,format,group 等
    success - visibility()
    updated: false
    success - onCreate()
    failed - visibility()
    updated: false
    failed - onCreate()

    // data set 的方法,收尾工作
    beforeClose()
    close()

    另,如果想定义一些用于全局的变量,可以定义在report 的 initialize() 方法里面,后面要使用的话就可以直接使用了。


    8. 碰上一些诸如在生成的report中点击链接更新数据库数据等,可以在dataset里面用以下代码,自己创建一个独立的statment来完成insert,update,delete等操作。

        updateTxn = MXReportTxnProvider.create(this.getDataSource().getName());

        updateStmt = updateTxn.createStatement();

        updateStmt.setQuery("update table"
        + " set value = 'aaa'"
        + " where id = 1";
        
        updateTxn.save();
        updateTxn = null;
    ----------------

    一些常用有用的sql 语句(用于oracle):

    to_date(trunc(add_months(sysdate,-1),'MM'),'yyyy-mm-dd')
    // 上个月的第一天
    to_date(trunc(sysdate, 'MONTH')-1,'YYYYMMDD')
    // 上个月的最后一天


    -----------------
    oracle function/storage procedure debug 用:

    set serveroutput on;    (命令窗口用,打开下面这个命令的输出)

    dbms_output.put_line(变量名或常量); (写入function和存储过程中,在命令窗口运行时会输出结

    果)

    ------
    要传入的参数个数不确定的function的写法, (先使用传入的参数构造sql语句,后面再用游标打开


    例子:

    DECLARE

           sqlstr VARCHAR2(500):= 'select * from table_1 where table_date >=

    to_date('''||param_1||''',''yyyy-mm-dd'') and table_1.id in ('||param_2||')';

     type my_cursor is ref cursor;    --声明REF CURSOR

     n_date_cursor my_cursor;    --定义REF CURSOR游标的变量

    BEGIN
    dbms_output.put_line(sqlstr);    --输出sqlstr的值到控制台

    open n_date_cursor for sqlstr;    --打开游标

    (下面对数据的处理略)
Open Toolbar