在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的基本類型