在java中有两种方式调用MySQL的存储过程,下面分别介绍:
1.环境准备
首先创建一个存储过程:
create procedure p_test(in count int,out rs varchar(1000)) begin declare curr int default 1; declare result_str varchar(1000) default ‘‘; cnt_loop:loop if curr > count then leave cnt_loop; end if; if curr = 1 then set result_str = concat(result_str,curr); else set result_str = concat(result_str,‘,‘,curr); end if; set curr = curr + 1; end loop cnt_loop; set rs = result_str; end;
上述存储过程用于拼接指定从1开始到指定值的数字,仅为演示说明。
2.使用JdbcTemplate调用
使用jdbcTemplate方式时,必须要设置不自动提交。另外调用时的参数必须对应,即使是输出参数也要指定占位符,设置输出的类型。
@Service @Slf4j public class ProcedureService { @Autowired private JdbcTemplate jdbcTemplate; public String test1() { final String[] str = {""}; Integer count = 20; jdbcTemplate.execute(new ConnectionCallback() { @Override public Object doInConnection(Connection connection) throws SQLException, DataAccessException { //不自动提交,即为手动提交 connection.setAutoCommit(false); //预处理,指定存储过程名和参数,?作为占位符,后面根据占位符赋值或设置输出值的类型 CallableStatement statement = connection.prepareCall("{ call p_test(?,?)}"); // 给存储过程中的输入参数赋值, statement.setInt(1, count); // 存储过程中的输出参数处理方式 statement.registerOutParameter(2, java.sql.Types.VARCHAR); statement.execute(); //获取返回的参数 str[0] = statement.getString(2); connection.commit(); return null; } }); log.info("返回的参数:{}", str[0]); return str[0]; } }
3.使用mybatis调用
在mybatis中调用,一般在xml中调用,而指定参数也有两种类型,一种是直接写在内部,一种是使用占位符,然后再声明。
3.1 实现类中dao方法
@Resource private ProcedureDao procedureDao; public String test2() { Integer count = 15; Map<String, Object> map = new HashMap<>(); map.put("count", count); procedureDao.pTest(map); String str = ""; if (map != null && map.get("result") != null) { str = map.get("result").toString(); } return str; }
参数需要使用map进行定义,其中输入参数需事先定义,输出参数在调用后直接从map中获取即可,无需对方法写返回值。
3.2 dao层定义方法
package com.zys.example.dao; import org.apache.ibatis.annotations.Mapper; import java.util.Map; @Mapper public interface ProcedureDao { void pTest(Map<String,Object> map); }
3.3 xml中调用存储过程
以下两种方式二选一即可。
1)直接写在内部
<select id="pTest" statementType="CALLABLE"> {call p_test( #{count,mode=IN,jdbcType=INTEGER}, #{result,mode=OUT,jdbcType=VARCHAR} ) } </select>
指定参数名,出入参类型及参数对应数据库的数据类型。
2)使用占位符方法
<select id="pTest" statementType="CALLABLE" parameterMap="pTestMap"> {call p_test(?,?)} </select> <!--定义参数--> <parameterMap id="pTestMap" type="java.util.Map"> <parameter property="count" jdbcType="INTEGER" mode="IN" /> <parameter property="result" jdbcType="VARCHAR" mode="OUT" /> </parameterMap>
个人推荐使用第二种方式,对参数清晰明了。
注意:
(1)上面两种方法在xml中必须指定statementType="CALLABLE",否则会报错。
(2)jdbcType是mysql数据库的类型,不是java的基本类型