知识库

推荐内容

快逸做的更好

产品优势

您的位置: 首页 > 知识库 > 设计基础 > 统计报表中巧用宏

统计报表中巧用宏

在面对海量基础数据时,统计报表的性能往往是重中之重.速度仿佛成了取胜之匙.我们在分析时发现,往往对于这种大数据量统计报表来说,直接面向基础数据进行处理有的时候并不是明智之举,因为sql执行速度也有瓶颈.这时,我们往往要用到中间表来提高速度.那么,在有并发的时候,如何来保证所抓取的数据都是最新的呢?


我们这里提供一种思路:


写一个存储过程,先清掉中间表的数据,然后进行数据抓取,填充到中间表中.利用报表的宏来执行这个存储过程,让报表抓取的数据都是最新的.


报表宏在整个过程中很关键,由于它的特性是在报表运算之前,系统会全面搜索整张报表的表达式定义,将所有的宏名替换成宏值.所以把执行存储过程的重任交给报表宏是再合适不过了.


首先,我们需要建立一个存储过程,来完成从基础表中抓取数据到中间表中的功能.由于这并不是本文的重点,此处省略存储过程的写法.


然后,我们分析以下存储过程的内容,由于它只是完成抓取并填充数据的过程,并无返回值,所以,我们还需要写一个自定义函数来执行.


例如:


import java.sql.CallableStatement;
import java.sql.Connection;
import java.util.Map;


import com.runqian.base4.resources.DataSetMessage;
import com.runqian.base4.resources.MessageManager;
import com.runqian.base4.util.Queue;
import com.runqian.base4.util.ReportError;
import com.runqian.base4.util.SQLTool;
import com.runqian.base4.util.Stack;
import com.runqian.report4.dataset.DataSet;
import com.runqian.report4.model.expression.Expression;
import com.runqian.report4.model.expression.Function;
import com.runqian.report4.model.expression.Node;
import com.runqian.report4.model.expression.Variant2;
import com.runqian.report4.usermodel.Context;
import com.runqian.report4.usermodel.DataSourceConfig;
import com.runqian.report4.usermodel.IConnectionFactory;
import com.runqian.report4.usermodel.IReport;



public class ExecProc extends Function {


 @Override
 public Object calculate(final Context cxt, final boolean arg1) {
  // TODO Auto-generated method stub
     try
      {
      final String dbName = cxt.getDefDataSourceName();
      final DataSourceConfig dsc = cxt.getDataSourceConfig(dbName); //获取系统数据源配置
      IConnectionFactory conFactory = null; //数据连接工厂


      Connection cn  = cxt.getConnection(dbName); //获取数据库连接对象
        if (cn == null ) {
         conFactory = cxt.getConnectionFactory(dbName); //未取到数据库连接,取同名数据连接工厂
         if (conFactory == null){ //无法获取正确数据库连接,返回错误信息
          final MessageManager mm = DataSetMessage.get();
          throw new ReportError(mm.getMessage(“error.noConnection”, dbName, dbName));
         }
         cn = conFactory.getConnection();
       }


        if ((cn == null) || (cn.isClosed()))
         throw new ReportError(“过程调用函数执行异常,无有效数据库连接”);
      String dbCharset = dsc.getDBCharset(); //获取数据库字符集
        if (dbCharset == null) dbCharset = “GBK”;
      String clientCharset = dsc.getClientCharset(); //获取本地字符集
      if (clientCharset == null) clientCharset = “GBK”;


       // String encoding = this.env.getDBCharset();
          if (this.paramList.size() == 0)
          throw new ReportError(“过程调用函数参数列表为空”);


        final Expression param1 = (Expression)this.paramList.get(0);
        final Object result1 = Variant2.getValue(param1.calculate(cxt, false),false,false);
        //Object result1 = Variant2.getValue(arg0, arg1, arg2)(param1.calculate());
        String sql = null;
        if (result1 instanceof String) {
          sql = (String)result1;
        }
        else
          throw new ReportError(“过程调用函数参数1应为字符串”);


        final CallableStatement proc = cn.prepareCall(sql);


        final int rn = 0;
        int i = 1; for (final int isize = this.paramList.size(); i < isize; ++i) {
          final Expression param = (Expression)this.paramList.get(i);
          if (param == null)
            throw new ReportError(“过程调用函数出现无效参数”);


          final Object result = Variant2.getValue(param1.calculate(cxt, false),false,false);
          SQLTool.setObject(1, proc, i, result, 9);
        }
        proc.execute();


        proc.close();
        return null;
      }
      catch (final Exception e)
      {
        throw new ReportError(“过程调用函数sql异常:” + e.getMessage(), e);
      }
      
 }


}


此自定义函数的功能就是执行这个存储过程,然后返回一个null.


接着,我们在报表中部署以下这个自定义函数,在customFunctions.properties中写入


ExecProc =0,ExecProc


这样自定义函数就部署好了.


最后,我们在报表里增加一个宏,然后调用:


例如:ExecProc(“call {procTest}”)



这样的话,整个过程通过报表宏得到了很好的解决.


总结:利用报表中强大的宏功能,我们可以完成多种报表需求,例如报表复用(利用宏动态改变表达式),报表排序等等.
 


本文标签:
发布日期:2011/08/30
本文分类: 设计基础