自定义函数实现报表call函数功能

使用前注意

由于增强函数是授权控制的功能点,所以这种在简单版本下实现增强函数的功能请慎用。本文介绍的方式适用于客户开发时使用的全功能临时授权,而正式购买的版本中无增强函数,销售要求在现有版本上实现增强函数的功能。

使用时可根据实际情况适当采用。

问题背景

某客户购买的报表开发版(无增强套件),而他们在开发报表阶段使用的是全功能临时授权,报表中使用了大量的call query seq等增强函数,正式上线时发现报表不可用,提示使用了增强函数。

客户处已无预算增购增强套件,销售要求在现有版本上实现报表call函数等功能。

问题分析

报表call函数的作用是调用存储过程,并将输出参数返回给报表。可以通过自定义函数,在程序里调用存储过程,并将输出参数作为自定义函数的返回值返回给报表。

所以在自定义函数中要实现如下几块功能:

1、 解析自定义函数中的传递的报表表达式参数,如:A1

2、 根据相应参数调用存储过程并接收存储过程输出参数;

3、 将输出参数值返回

具体实现

自定义函数名:callProcedure,参数:存储过程名,输入参数

1、 接收参数,并解析

// 取得第一个参数,默认为表达式,需要把该表达式算出来,结果才是函数的参数值

Expression param1 = (Expression) this.paramList.get(0);

Expression param2 = (Expression) this.paramList.get(1);

// 算出参数值

Object result1 = Variant2.getValue(param1.calculate(ctx, isInput),false, isInput);

Object result2 = Variant2.getValue(param2.calculate(ctx, isInput),false, isInput);

2、 调用存储过程

//获取ctx中保存的连接工厂连接

conn = ctx.getConnectionFactory(“mysqlProc”).getConnection();

//调用存储过程

cstmt = conn.prepareCall(“{call “+procName+“(?,?)}”);

cstmt.setString(1, inParam);//设置第一个输入参数值

cstmt.registerOutParameter(2, Types.VARCHAR);//OUT 参数注册为JDBC 类型sqlType

cstmt.execute();

outParam = cstmt.getString(2);//接收输出参数的值

3、 将输出参数值返回给报表

returnoutParam;//函数返回值

源程序:

1、 mysql存储过程

create procedure nameProc(

in id varchar(10),

out name varchar(50)

)

begin

set name =CONCAT(id,’aaa’);

end

2、 自定义函数CallProcedure.java

packagecustomFunction;

importjava.sql.CallableStatement;

importjava.sql.Connection;

importjava.sql.ResultSet;

importjava.sql.SQLException;

importjava.sql.Statement;

importjava.sql.Types;

importcom.runqian.base4.resources.EngineMessage;

importcom.runqian.base4.resources.MessageManager;

importcom.runqian.base4.util.ReportError;

importcom.runqian.report4.model.expression.Expression;

importcom.runqian.report4.model.expression.Function;

importcom.runqian.report4.model.expression.Variant2;

importcom.runqian.report4.usermodel.Context;

publicclassCallProcedure extendsFunction{

publicObject calculate(Context ctx, booleanisInput) {

/**

*计算报表参数

*/

//判断参数个数

if(this.paramList.size() < 1) {

MessageManager mm = EngineMessage.get();

thrownewReportError(“encrypt:”

+ mm.getMessage(“function.missingParam”));

}

// 取得第一个参数,默认为表达式,需要把该表达式算出来,结果才是函数的参数值

Expression param1 = (Expression) this.paramList.get(0);

Expression param2 = (Expression) this.paramList.get(1);

if(param1 == null) {// 判断参数是否为空

MessageManager mm = EngineMessage.get();

thrownewReportError(“encrypt:”+ mm.getMessage(“function.invalidParam”));

}

if(param2 == null) {// 判断参数是否为空

MessageManager mm = EngineMessage.get();

thrownewReportError(“encrypt:”+ mm.getMessage(“function.invalidParam”));

}

// 算出参数值

Object result1 = Variant2.getValue(param1.calculate(ctx, isInput),false, isInput);

Object result2 = Variant2.getValue(param2.calculate(ctx, isInput),false, isInput);

// 判断第一个参数值是否为空

if(result1 == null) {

returnnull;

}

if(result2 == null) {

returnnull;

}

String procName = result1.toString();//存储过程名

String inParam = result2.toString();//输入参数

Connection conn = null;

CallableStatement cstmt = null;

Statement stmt = null;

ResultSet rs = null;

String outParam = null;

try{

//获取ctx中保存的连接工厂连接

conn = ctx.getConnectionFactory(“mysqlProc”).getConnection();

//调用存储过程

cstmt = conn.prepareCall(“{call “+procName+“(?,?)}”);

cstmt.setString(1, inParam);//设置第一个输入参数值

cstmt.registerOutParameter(2, Types.VARCHAR);//OUT 参数注册为JDBC 类型sqlType

cstmt.execute();

outParam = cstmt.getString(2);//接收输出参数的值

} catch(Exception e) {

// TODOAuto-generated catch block

e.printStackTrace();

}finally{

try{

if(cstmt!=null)

cstmt.close();

if(conn!=null)

conn.close();

} catch(SQLException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

}

returnoutParam;//函数返回值

}

}