使用iBatis调用存储过程时的XML文件配置
iBatis(现在更名为myBatis了)可以被看做是一个"半自动化"的ORM工具(通过sql-mapper),或者更严格的说,是一个关于JDBC API的强大封装。简单易学是它的优点,这也就是为什么在很多项目中,我都倾向于使用iBatis,尤其是提供大量复杂查询或者报表功能的应用当中。
在<<iBatis in Action>>这本书中,讲解了关于iBatis的各种用法,但是作者也特别强调了:在Dataaccess这层上,通过调用存储过程是一个反模式,不推荐使用;于是关于通过iBatis调用存储过程,只是非常简单的一笔带过。
但是我们也通常会在很多场合中,遇到要使用存储过程的情况。就存储过程本身,以Oracle存储过程为例,我们完全可以在一个jdbc事务里面,完成有多个前后依赖步骤的较为复杂的数据库访问,从而减少应用与数据库之间的往返通讯。
在这里,以Oracle数据库为例,讲述通过iBatis调用Oracle存储过程时的配置思路。在这里我假定阅读此文的人有关于iBatis的使用经验,从而可以略过一些细节描述。
先看一下Oracle存储过程接口:
PROCEDURE r_process_order(is_oid IN VARCHAR2, -- 订单号 is_taskid in varchar2, --任务单号 is_price in number, --价格 is_gap in number, --浮动价差 is_notes in varchar2, --备注 is_timelimit in number, --报价有效时间限制 is_userid in varchar2, -- 用户编号 is_deptid in varchar2, -- 用户所在部门id oi_flag OUT INTEGER, --0 成功 -1 错误 os_msg OUT VARCHAR2, --出错信息 os_finish out varchar2, --是否完成订单流程 0否 1是 or_order_item_list out sys_refcursor, -- 订单条目信息 or_task_item_list out sys_refcursor, -- 后续待办事项信息 or_userlist out sys_refcursor -- 广播通知的用户集 );
<!-- 订单:应答 --><parameterMap id="map_r_process_order" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN" /><parameter property="taskId" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN" /><parameter property="price" jdbcType="DOUBLE" javaType="java.math.BigDecimal" mode="IN" /><parameter property="gap" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN" /><parameter property="notes" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN" /><parameter property="userId" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN" /><parameter property="deptId" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN" /><parameter property="flag" jdbcType="INTEGER" javaType="int" mode="OUT" /><parameter property="msg" jdbcType="VARCHAR" javaType="java.lang.String" mode="OUT" /><parameter property="strFinish" jdbcType="VARCHAR" javaType="java.lang.String" mode="OUT" /><parameter property="orderItemList" jdbcType="ORACLECURSOR" javaType="java.sql.ResultSet" mode="OUT" resultMap="orderItemListResult" /><parameter property="taskItemList" jdbcType="ORACLECURSOR" javaType="java.sql.ResultSet" mode="OUT" resultMap="taskItemListResult" /><parameter property="processUserIds" jdbcType="ORACLECURSOR" javaType="java.sql.ResultSet" mode="OUT" resultMap="processUserId" /></parameterMap><procedure id="r_process_order" parameterMap="map_r_rfq_reply">{ call p_foo_bar_manager.r_process_order(?,?,?,?,?,?,?,?,?,?,?,?,?)}</procedure>