润乾自定义函数实现报表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;//函数返回值
}
}