procedure

清明节

44日至46日,共3

47日(星期日)上班

劳动节

429日至51日,共3

427日(星期六)、428日(星期日)上班

 
 
 
增加....................................
说明: 新增加“存储过程”调用组件,可自动检索当前DB中已有的用户创建的存储过程,进行勾选后配置出入参即完成存储过程调用
问题分析:
1,当前db:会提供数据源列表,待分析 
2,数据库产品的区分:
3,出入参数的获取与配置(是存储过程调用组件,而不是创建组件):会提供接口访问,待分析
 
//解决过程
 
/设计需求分析
 
./在工具栏添加一个组件
../MessageflowElementTypes的添加是否和plugin配置关联.....................待
../书写ServiceConfig子类时,不需要重写父类(ServiceConfig)的 String getUsedTypeName() 方法,返回组件中引用的类型名称
 
./存储过程及参数,变量的获取
../DataBaseInfoConfigManager 要通过数据源名称和schema名称才能获取存储过程;数据输入组件里有关于schema的获取
../获取存储过程和参数列表需要通过远程调用apusic-esb-base的IDataBaseInfoConfigManager提供的接口的方法,详细如下:
增加在DataBaseInfoConfigManager已有的getProcedures方法与getProcedureColumns方法到IDataBaseInfoConfigManager,然后将此apusic-esb-base工程导出为jar包(注意和工程相关的xml配置文件不用勾,和test相关的也不用勾),替换掉com.apusic.esb.designer.core里的apusic-esb-base.jar包,即可在DatabaseComponentUtil里通过IDataBaseInfoConfigManager调用接口提供的新方法
注:if (DBType.ACCESS.equals(dbType) || DBType.FOXPRO.equals(dbType))
 
 
 
注意由于替换jar包后可能在svn里会导致冲突,所以要保证apusic-esb-base工程的代码是最新的,打的jar包也是最新的,这样在冲突的情况下就可以标记为合并,并且提交自己的jar包
 
../通过资源IResource去获取服务器的调用接口:IESBServerManager.INSTANCE.getInvoker(),如果未登录引擎,则可能返回null
 
../从服务器接口获取存储过程列表及参数列表时,不会返回null,而是返回空列表或者有元素的列表
 
./组件配置的widzard设计及配置相关的模型与持久化
../表格中的数据监听修改的parameterList<Parameter>是直接修改的,setInput的特点,对象的特点。。。。。。。。。。。。。待
../为什么对于控件的修改不用重新启动设计器就能看到效果
 
./配置信息的保存
../关于addVarable()方法,不用再添加变量了,因为没有产生新的变量....................待
 
 
 
./全面清理
 
1,不同数据库之间有没有需要校验的地方 V
关于:if (DBType.ACCESS.equals(dbType) || DBType.FOXPRO.equals(dbType)),用在获取schema的时候(DatabaseComponentUtil.getSchemas())
获取数据源与模式列表的方法都是现成的,只接能用就行了
 
2,file和folder
 
3,初始化情形: V
新组件第一次打开时,完成按钮是无效的,数据源列表会先获取到,但是不会选中(没有默认选中值),这样可以设置联动的下拉选择,并且在新选择不等于原选择时,才采取一些动作。
 
旧组件第二次打开(着重分析配置项不再存在时的情形):判断旧组件的方式是判断模型中的数据源是否存在,如果存在,则配置文件的内容(即模型的所有属性)都是完整的;只需再判断原配置的值在新获取的列表中存不存在(如某个存储过程可能已删掉了),如果不存在,则要先加入到combo里,这样才能在用户操作前选中原配置的值
 
注意combo的setText()是不会触发select事件的,初始化也是在addListener之前
 
 
4,无元素List 及 null 校验的统一 V
获取数据源,模式,存储过程列表的时候,如果找不到,都要返回空列表,在转换成数组(以便设入combo里)时,都可以用如下方式:
schemaItems = schemaList.toArray(new String[schemas.size()]);
也可以将new String[schemas.size()]改为new String[0],则会生成另一个数组赋给schemaItems;因为String[schemas.size()]的空间刚好够放schemaList的元素,所以就不用再生成另一个数组保存元素值
 
5,变量类型的校验 V
存储过程的类型名的返回值是怎样的(用int型标识),如果是 nchar,nvarchar,varchar,bit,bool之类的是否无经过处理(已经被jdbc封装)
 
6, V
添加组件的图片及格式的确定
描述信息右边的图片需要更换
存储过程对话框用到的图片须要修改
 
7,向导页面中构造方法里最后一句是配置帮助文档的
 
8,注释修改 V
 
 
/引擎部分代码分析:
 
./jdbc是否对存储过程和函数统一对待。。。。。。。。。。。。。。。。。。。。。待
 
./无法将配置界面的sql类型转换为sdo类型来显示,因为一种sql类型对应多种sdo类型,那些sdo类型的显示格式是不一样的
 
./不懂的代码部分.............待:
 
../handler:
 
(1)
if (dsName.indexOf("@") > 0) {
            dsName = dsName.substring(0, dsName.indexOf("@"));
}
 
(2)通过数据源名称获取系统的数据源服务
conn = storedProcedure.getMessageServiceContext().getConnection(dsName);
 
(2)
sdo相关:
-> 从 sdo path 的字符串获取到SDOPath(一般的组件是通过最终变量名从msgs获取到最终变量值的,因为有生成变量)
-> 通过SDOUtil.parseSdoPath(String text)方法,返回第一个找到的sdo path,例如${httpdata/p1},返回一个SDOPath对象,其中:
    变量名为 httpdata;
    childPath为 p1;    
    originalPath为 ${httpdata/p1}
-> 通过SDOUtil.getValueAsObject(Map<String, DataObject> msgs, SDOPath path)获取到最终变量值:
    通过Object SDOPath.getVariableName()从msgs获取对应的DataObject;
    如果path.getChildPath().equals("/"),即不含子路径了,则返回此DataObject;
    否则返回DataObject.get(path.getChildPath())的值,是否传入一个路径字符串就能获取到DataObject最终的值,而返回类型为Object..............待
-> 获取变量的类型:
Type variableType = msgs.get(sdoPath.getVariableName()).getType();
if (!StringUtil.isEmpty(sdoPath.getChildPath())) {// 如果存在子路径,则需要查找子路径的Type,否则之需要使用变量的Type
                        variableType = SDOUtil.parseValueType(variableType, sdoPath.getChildPath());
}
   
   是否通过最终的DataObject就可以....各路径都有dataObject吗?
 
->关于Type.getProperty(property).getType()和type.getProperty(property).getType()
 
 
 //可能要做的修改
/变量类型的校验:
 
问题:
(1)当组件配置中对应的变量不存在时,即组件显示X时,打不开配置对话框了,这是由于打开配置对话框时要获取变量的类型
但是变量已经不存在了
(2)面对种类繁多的数据库字段类型,用户不知道具体应该选择哪一种变量类型
(3)当选择一个父变量时,类型校验也抛错
 
解决方式,把选取变量时直接先过滤掉不可选的,省去了变量类型的校验,用户也知道应该选择什么类型的变量
变量类型及用户使用的优化,参考http://blog.csdn.net/gaojiewang/article/details/7580349....................待
 
目前保守的方式:
使用时用户须自己知道需要什么样类型的变量,可以使用java转换去产生
在配置对话框第一次启动时不用校验,就是在代码中加个标志位
   
/引擎部分代码:
注册输出参数的类型不用通过SDOPath,因为parameter那里已经有保存了!
 
 
/bug修改:
AESB-1853【存储过程】调用存储过程问题:
1-1,number类型对应BigDecimalObject类型
1-2,Long类型是对应字符串类型的
2-1,已测试成功
 
其他:
java调用存储过程报模式不对的问题:http://harveyzeng.iteye.com/blog/1660953
据说只有Sybase有这个毛病,其它的数据库都没有这个问题
sp_procxmode proc1, 'anymode'
 
返回结果参数的过程的语法为: 
{? = call 过程名[(?, ?, ...)]} 
 
../存储过程的参数类型怎么有6种
参考:http://blog.csdn.net/zwei1121/article/details/695502
 
 
重构.......................................................................................
/了解各种数据库存储过程的特点及使用JDBC调用的方式
 
./mysql
1,参数列类型为 in out inout 当为out在JDBC为return
2,可能返回结果集和更新计数
3,不支持return语句
 
./ms server
1,存储过程名: procedure_name [ ; number ],
是可选的整数,用来对同名的过程分组,以便用一条 DROP PROCEDURE 语句即可将同组的过程一起除去。例如,名为 orders 的应用程序使用的过程可以命名为 orderproc;1、orderproc;2 等。DROP PROCEDURE orderproc 语句将除去整个组。如果名称中包含定界标识符,则数字不应包含在标识符中,只应在 procedure_name 前后使用适当的定界符。
2,支持游标,但mircosoft jdbc 不支持游标类型,所以只能用select语句返回结果集
 
3,关于return值的获取
return ; 返回0
return n; 返回n
无return 返回0
是通过构造形如 {?=call pro_select;1(?,?)} 的第一个参数来获取的,但是用jdbc获取ms server的存储过程参数时没有返回值列,所以要自己去识别与构造
 
4,过程中的out参在jdbc中被识别为in_out,应该是可以传入值的
 
 
 
./oracle
 
1,out在jdbc中被识别为return
 
2,存储过程不能用return返回参数,但可以用return ;
 
3,不可以用select 语句返回结果集
 
4,对oracle返回结果集的问题暂不处理
oracle的游标知识可参考http://benchild.iteye.com/blog/503360
 
 
./sybase
 
1,可以有return和return n形式,jdbc处理sybase存储过程时会自动加上返回值列,列名为RETURN_VALUE;数据类型为int;列类型为result;所以在拼存储过程时如果有这一列,就加上它的返回值列,使用其他没有返回值列的,就抛弃返回值列
 
注:最好统一处理,抛弃返回值列好了!
 
2,可以用select返回结果集
 
 
./db2
 
1,db2中存储过程中定义的out参数在jdbc中也显示为return
 
2,如果要在存储过程中操纵表,则:reorg table DB2ADMIN.person1
 
3,不支持return语句
 
4,通过定义游标返回结果集,但在jdbc中是用getResultSet()方法获取,不作为参数列
参考:http://wenku.baidu.com/view/8663e312f18583d049645952.html
含游标的存储过程定义参见db2_cursor.sql
 
 
 
./informix
..........................................至此,调试出错!
 
./神通
 
./人大金仓
 
./达梦
 
 
./统一处理小结:
措施1:当参数列的方向,即列类型为result或unknow时,抛弃这些列,不对返回值作处理;
因为:mysql,oracle都不能用return,如果要使用,以后可能要对能用或不能用的情况作两种处理
 
措施2:获取一个存储过程的列类型,当为result或unknow时,作返回值处理,把列名定为return_value
(unknow应该是数据库提供的jdbc接口的支持不完善导致)
 
措施3:对游标也可以统一处理,只要知道各种存储过程游标参数所对应的sqltype就可以进行适匹了
oracle游标: OTHER 1111
 
 
/生成结果集相关变量的方式,注意是多个结果集
遇到问题: 在存储过程执行前是无法确定结果集的格式的,所以只有当用户配置好本组件后按finish就调用一次存储过程,然后返回ResultSet,就能获取到结果集的MeteData,从而构造流程变量.但问题是,存储过程可能返回一个或多个结果集,结果集的格式可能是各不相同的,问题就归纳到:怎样用通用的方式创建一个已知数据结构的,复杂的Schema
 
 
/参数变量类型过滤的问题:
发现还有一个工具类的方法:SDOTypes.getSDOTypeBySQLType()
数据库字段和java类型的对应关系:http://blog.csdn.net/gaojiewang/article/details/7580349
 
 
/各种数据库类型适配的工具:
DBType dbType = DataSourceUtil.guessDBType(conn);
 
 
 
 
 
 
 
 
/分析过程总结:
分析问题解决所需要的大概过程:
st1:分析JDBC对存储过程相关提供的接口的功能及使用
st2:分析各种数据库的存储过程在JDBC中的调用方式
st3:分析结果集对应编程变量生成的可能性 (在下一个版本再做)
st4:编码过程:(须要进一步进行分解)
st4-1:因为生成结果集流程变量的过程比较复杂,所以先放下 (在下一个版本再做),先完成st4-2
 
st4-2:处理除结果集及游标以外相关的存储过程调用的bug:
./一切以参数为中心,如果JDBC获取存储过程参数中有result或unknow的类型,则作过程返回值处理,调用的字符串格式为: {?=call pro_select(?,?)}
 
 
 
/处理过程(都暂不支持返回结果集,如果使用结果参数,则必须将其注册为 OUT 参数):
 
./存储过程需要获取出参,返出值,需要支持主流数据库mysql,ms server,oracle,sybase,db2
 
st1,mysql要处理的情形
无参数存储过程 ......V
有inout,out(return)参数的情形 ......V
 
st2,ms server
暂不支持返回值形式 ......V
无参数存储过程 ......V
有return n;形式语句的情形 ......V
有in out inout参数的情形 ......V
 
st3,oracle
无参数存储过程 ......V
有in out(return) inout参数的情形 ......V
 
st4,sybase 
无参数存储过程 ......V
有in out return inout参数的情形......V
 
注:
无论怎样都有有RETURN_VALUE(int result)的情形;
语句中不能用分号,创建过程后要加上一句:如 ,
sp_procxmode pro_no_param, 'anymode'
 
st5,db2
无参数存储过程 ......V
有in out(return) 过程调用 ......V
 
st6,informix
无参数存储过程(也没有result的列) ......V
无参数存储过程(有result的列)..........待
有有in out(return) 过程调用...........待
 
好像如果要有result列的话,就要先有出入参数列JDBC才会加上result列
 
 
/其他总结:
./当心里有一种编码风格规范与要求时,就能让自己写的代码越来越专业
 
 
 
/获取结果集的处理代码:
 
private void getResultSet(CallableStatement cs) throws SQLException {
        ResultSet rs = null;
        int updateCount = -1;
        boolean flag = cs.execute();
 
        do {
            updateCount = cs.getUpdateCount();
            if (updateCount != -1) {// 说明当前行是一个更新计数
                // 处理.
                System.out.println("updateCount: " + updateCount);
                cs.getMoreResults();
                continue;// 已经是更新计数了,处理完成后应该移动到下一行
                // 不再判断是否是ResultSet
            }
            rs = cs.getResultSet();
            if (rs != null) {// 如果到了这里,说明updateCount == -1
                // 处理rs
                showRS(rs);
                cs.getMoreResults();
                continue;
                // 是结果集,处理完成后应该移动到下一行
            }
            // 如果到了这里,说明updateCount == -1 && rs == null,什么也没的了
 
        } while (!(updateCount == -1 && rs == null));
        // cs.getXXX(int);//获取输出参数
    }
 
    private void showRS(ResultSet rs) throws SQLException {
        System.out.println("ResutlSet:................................ ");
        while (rs.next()) {
            System.out.println(rs.getString(1));
            System.out.println(rs.getString(2));
            System.out.println(rs.getInt(3));
        }
        System.out.println("........................................... ");
    }
 
 
            // cstmt = conn.prepareCall("{call testpro1(?)}");
 
            // cstmt = conn.prepareCall("{?=call test_select(?,?)}");
            // cstmt.registerOutParameter(1, java.sql.Types.INTEGER);
            // cstmt.setObject(2, "3");
            // cstmt.setObject(3, "3");
            // cstmt.registerOutParameter(3, java.sql.Types.VARCHAR);
 
 
 
            // 获取返回值
            // int ret = cstmt.getInt(1);
            // int out = cstmt.getInt(4);
            // System.out.println(ret);
            // System.out.println(out);
 
 
                    
 
/jira单的一些描述:
本组件功能描述如下几点: 
1,暂不支持存储过程中有返回结果集的情形 
2,暂不支持存储过程中有定义游标的情形 
3,目前支持的(需要测试的)数据库有5个: 
    mysql, sql server, oracle, sybase, db2 
4,由于mysql,oracle,db2中存储过程(不是函数)不支持用return语句返回整形状态值,jdbc在获取sql server存储过程的参数列时没有返回值那一列,所以只对sybase存储过程中用return语句返回的值有作处理可以获取 
 
1,oracle 的 number类型对应流程中的decimal类型, Long类型不是指java中的长整形,数据类型的对应关系可参见:http://blog.csdn.net/gaojiewang/article/details/7580349
 
2,sybase存储过程参数列第一列名称为RETURN_VALUE,即是过程返回值;在数据库中创建好存储过程后,如果是普通的非事务型的,则要在数据库中执行如下命令,否则在流程中调用会出错:
sp_procxmode procedureName, 'anymode'
 
3,目前该组件只支持mysql,ms server,oracle,sybase,db2 5个数据库
 
 
1,选变量时做了过滤,只能选择对应的类型
2,列表已改为会刷新
3,;n的形式是数据库存储过程分组的标识,因为可能有, procedureName;1和procedureName;2的情形
4,按键的显示是由图片撑起,已调整,在linux和win7上能显示完全,在xp上稍微不同
5,由于作了变量过滤,不会再出现这种情形了
6,已修正
 
 
/删除的代码:
 
if (value instanceof java.util.Date) { //将Date类型转换为最完整的时间锉格式,以使setObject()方法自动转换成适合数据库的类型
                        java.sql.Timestamp sqlDate = new java.sql.Timestamp(((java.util.Date) value).getTime());
                        cstmt.setObject(i + 1, sqlDate);
                    } else {
                        cstmt.setObject(i + 1, value);
                    }
 
 
/**
     * 判断变量的类型与存储过程参数的类型是否一致
     * 
     * @param dataType 参数的类型标识
     * @param varPath 变量path
     * @param ProcessPackage
     * @return boolean
     * */
    public static boolean isParameterTypeEquals(int dataType, String varPath, ProcessPackage pg) {
        if (StringUtil.isNullOrEmpty(varPath)) {
            return false;
        }
        SDOPath sdoPath = SDOUtil.parseSdoPath(varPath);
        Map<String, Type> varMap = pg.getGlobalVariables();
        Type variableType = varMap.get(sdoPath.getVariableName());
        if (variableType == null) {
            varMap = pg.getVariables();
            variableType = varMap.get(sdoPath.getVariableName());
        }
        if (!StringUtil.isEmpty(sdoPath.getChildPath())) {// 如果存在子路径,则需要查找子路径的Type,否则只需要使用变量的Type
            variableType = SDOUtil.parseValueType(variableType, sdoPath.getChildPath());
        }
 
        int varType;
        varType = SDODataTypeHelper.sqlTypeFor(variableType);
        if (dataType == varType) {
            return true;
        }
        return false;
    }
 
 
 
触发器.................................................................................................................
`PROCEDURE` 是 MySQL 中用于创建存储过程的关键字。存储过程是一组预先编写好的 SQL 语句集合,可以在需要的时候执行。使用存储过程可以将常用的 SQL 语句封装起来,方便重复使用,并且可以提高 SQL 执行效率。 创建存储过程的语法如下: ``` CREATE [DEFINER = { user | CURRENT_USER }] PROCEDURE sp_name ([proc_parameter[,...]]) [characteristic ...] routine_body proc_parameter: [ IN | OUT | INOUT ] param_name param_type characteristic: COMMENT 'string' | LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } routine_body: valid_sql_statement ``` 其中,`sp_name` 是存储过程的名称,`proc_parameter` 是存储过程的参数列表,`characteristic` 是存储过程的特性,`routine_body` 是存储过程的主体部分,包括一系列有效的 SQL 语句。 例如,下面的示例代码创建一个名为 `get_customer` 的存储过程,它接受一个客户 ID 作为输入参数,然后从 `customers` 表中检索出该客户的信息: ``` CREATE PROCEDURE get_customer (IN customer_id INT) BEGIN SELECT * FROM customers WHERE id = customer_id; END; ``` 在这个例子中,`IN customer_id INT` 指定了一个输入参数 `customer_id`,它的类型为 `INT`。`SELECT` 语句用于检索出指定客户 ID 的信息。该存储过程可以在需要的时候调用,例如: ``` CALL get_customer(123); ``` 这将检索出客户 ID 为 123 的客户信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值