mybtais调用{? = call procName(?,?) }存储过程


工作中要将ssh项目中的功能改造成springboot项目接口,遇到了调用存储过程的问题,进行一下记录

存储过程示例

一个简单的oracle获取序列值的存储过程

CREATE OR REPLACE FUNCTION FC_seq_result(p_seqname IN VARCHAR2,
                                         p_type    IN NUMBER) RETURN NUMBER IS
  v_seq    VARCHAR2(1024);
  v_pro    VARCHAR2(1024);
  v_result NUMBER(10);
BEGIN
  IF p_type = 1 THEN
    v_pro := '.NEXTVAL';
  ELSIF p_type = 0 THEN
    v_pro := '.CURRVAL';
  END IF;
  v_seq := 'SELECT ' || p_seqname || v_pro || ' FROM DUAL';
  EXECUTE IMMEDIATE V_SEQ
    INTO V_RESULT;
  Return(v_result);
END;

ssh实现代码:

/***
	 * 获取Seq值,type为1获取nextval;type为0获取currval
	 * 
	 * @param sqNm
	 * @param type
	 * @return
	 * @throws Exception
	 */
	public String getSquenceValue(String sqNm, int type) throws Exception {
		Connection conn = null;
		CallableStatement pstmt= null;
		ResultSet rs = null;
		try {
			conn = SessionFactoryUtils.getDataSource(getSessionFactory()).getConnection();
			pstmt = conn.prepareCall("{? = call FC_seq_result(?, ?)}");
			pstmt.setString(2, sqNm);
			pstmt.setInt(3, type);
			pstmt.registerOutParameter(1, Types.NUMERIC);
			if ("sqlserver".equals(getDbType())) {
				rs = pstmt.executeQuery();
				while (rs.next()) {
					return rs.getString(1);
				}
				throw new Exception("获取Sequence失败,[" + sqNm + "]");
			} else {
				pstmt.executeUpdate();
				Object obj = pstmt.getObject(1);
				if (null != obj && !"".equals(obj.toString())) {
					String seqVal = obj.toString();
					return seqVal;
				}
			}
		} catch (Exception e) {
			throw new Exception("获取Sequence失败,[" + sqNm + "]");
		} finally {
			if (null != rs) rs.close();
			if (null != pstmt) pstmt.close();
			if (null != conn) conn.close();
		}
		throw new Exception("获取Sequence失败,[" + sqNm + "]");
	}

通过上边的代码我们可以看到:
代码中通过 { ? = call procName(?,?) } 这种方式调用的存储过程,第一个 是返回值结果。这种方式感觉比较特别,试了几种方式,终于成功了。

使用mybatis来实现这种方式的存储过程的调用

使用Map类型来做出入参的接收

  1. 首先我们来定义返回值,入参,及在mapper.xml中调用的写法,示例:
  <select id="getSquenceValue" parameterType="java.util.Map" statementType="CALLABLE">
		{ #{map.seqNo,mode=OUT, jdbcType=NUMERIC} = call FC_seq_result(#{map.seqName,mode=IN, jdbcType=VARCHAR}, #{map.type,mode=IN, jdbcType=INTEGER})}
  </select>

我们使用 mode=OUT 来定义返回值,mode=IN 来定义入参,jdbcType 来定义类型,statementType="CALLABLE"来声明调用的是存储过程。
其中,map是我mapper.java定义的@Param(“map”)参数。

  1. 然后我们来定义mapper.java中的方法:
void getSquenceValue(@Param("map") Map<String, Object> map);
  1. 再来看service如何调用mapper.java的方法
    /**
     * mybatis调用存储过程,根据序列名获取序列值
     * @param seqName
     * @param type
     * @return
     */
    private String getSquenceValue(String seqName,Integer type) {
    Map<String, Object> paramMap = new HashMap<String, Object>(4);
    paramMap.put("seqNo",new BigDecimal("0"));
    paramMap.put("seqName",seqName);
    paramMap.put("type",type);
    mapper.getSquenceValue(paramMap);
    return paramMap.get("seqNo").toString();
  }

这样就实现 ?=call procName(?,?) 这种存储过程的返回值的获取。

参考文章:

https://blog.csdn.net/cs373616511/article/details/82890306

注意事项[上边参考文章也有提到]:

1、 存储过程的参数和名称无关,只和顺序有关系
2、 存储过程的output参数,只能通过传入的map获取
3、 存储过程返回的结果集可直接用返回的map接收
4、 存储过程的return结果需要使用?=call procName(?,?)的第一个参数接收,需要指定对应的mode为OUT类型
5、 存储过程对应的数据类型为枚举类型,需要使用大写,如VARCHAR
output是在存储过程中的参数的返回值(输出参数),而ReturnValue是存储过程返回的值(使用return关键字),一个存储过程可以有任意多个依靠参数返回的值,但只有一个ReturnValue。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值