MyCat1.6带返回参数存储过程调用示例

本例环境:SpringMVC3.x + Mybatis3.x + Mycat1.6 + Mysql5.6。

1、创建带出参存储过程

DELIMITER &&  
CREATE  PROCEDURE `test_proc`( in a_id int , out a_goods_id int)
BEGIN  
              SELECT  a.goods_id  INTO  a_goods_id  
              FROM  es_goods_community a  
              WHERE  a.id=a_id ;  
END &&

DELIMITER ; 

备注:这里的存储过程比较简单,就是根据一个表的ID,返回一个表的另外一个字段,本例中a_goods_id为出参。


2、mybatis映射文件

 

<select id="testCallProc" resultType="java.lang.Integer">  <!-- statementType="CALLABLE" -->
         <![CDATA[
       /*!mycat:sql=select 1 from es_goods_community where seller_id=26*/{call test_proc(
              #{id,mode=IN,jdbcType=INTEGER},
              @goodsId
           )};select @goodsId;
       ]]>

    </select>

这里的关键:statementType="CALLABLE"不需要加上,而是把存储过程当成一条普通的SQL语句,发送给mycat执行,mycat根据注解路由到具体的后端节点,然后执行之,并返回结果,还需要在后面使用selelect语句返回OUT参数。在call语句中,出参用@加变量名定义,名字与select语句中的名字保持一样即可。

为什么要这样写呢?原因如下:

  • mycat已经声明,存储过程的调用通过注解来支持(主要原因,调用存储过程的语句无法定位路由信息),如果statementType="CALLABLE",mysql客户端(本例指mysql驱动包)会把语句当存储过程来看到,势必需要知道存储过程的元数据(出参列表)。故在mybatis文件中,call语句之前需要待上注解,但这和mycat驱动包处理存储过程的代码产生了矛盾,如下代码:
  • public CallableStatement(MySQLConnection conn, String sql, String catalog,
                boolean isFunctionCall) throws SQLException {
            super(conn, sql, catalog);
    
            this.callingStoredFunction = isFunctionCall;
    
            if (!this.callingStoredFunction) {
                if (!StringUtils.startsWithIgnoreCaseAndWs(sql, "CALL")) {      // @1
                    // not really a stored procedure call
                    fakeParameterTypes(false);      //@2
                } else {
                    determineParameterTypes();  //@3
                }
    
                generateParameterMap();
            } else {
                determineParameterTypes();
                generateParameterMap();
    
                this.parameterCount += 1;
            }
    
            this.retrieveGeneratedKeys = true; // not provided for in the JDBC spec
        }

       代码来源与mysql-connector-java-5.1.30.jar中CallableStatement,现在做个简单的解读:

       代码@1,判断SQL语句是否以CALL语句开头,如果不是,则调用代码@2fakeParameterTypes方法, 我可以很负责任人的

                       告诉你,该方法只是固定返回一个参数列表,完全与调用的存储过程的出参列表不匹配

       代码@3,调用后端连接,得到存储过程的源信息:发送的语句为:                 

           SELECT name, type, comment FROM mysql.proc WHERE name like '存储过程名' and db <=> '数据库

          名' ORDER BY name, type;

     但mycat的处理如下:io.mycat.server.ServerConnection 的public void execute(String sql, int type) 方法:

跟进MysqlProcHandler.handle方法得知,mycat只是返回空数据给前端连接,并没有去后端执行该语句。所以,mybatis配置文件的statementType不能陪在为CALLABLE的原因。

3、DAO与控制层的代码就在这里省略。

完整的代码如下:http://git.oschina.net/zhcsoft/StudyDemo  包路径为:persistent.prestige.web下。

备注:不能在mysql客户端连接工具(连接mycat)中直接运行:

call test_proc(140,@goodsId)};select @goodsId;得不到正确的数据原因分析:

因为在客户端查询分析器中执行该命令,,是分两条语句 call test_proc(140,@goodsId);  select @goodsId;两条命令发送给mycat执行的,这样发送到后端的连接,两次不一定使用相同的Connection连接,所以无法得到值,

call test_proc(140,@goodsId);  select @goodsId; 必须当成一个multi-statement语句一起发送给mycat,才能正确得到结果。

再次声明:完整的示例代码地址:http://git.oschina.net/zhcsoft/StudyDemo 

欢迎加笔者微信号(dingwpmz),加群探讨,笔者优质专栏目录:

1、源码分析RocketMQ专栏(40篇+)
2、源码分析Sentinel专栏(12篇+)
3、源码分析Dubbo专栏(28篇+)
4、源码分析Mybatis专栏
5、源码分析Netty专栏(18篇+)
6、源码分析JUC专栏
7、源码分析Elasticjob专栏
8、Elasticsearch专栏
9、源码分析Mycat专栏

 

 

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中间件兴趣圈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值