MyBatisでストアドプロシージャを使う
MyBatisを用いたJavaプロジェクトにて、MySQLのストアドプロシージャ(Stored Procedure)を呼び出そうとして戦った記録
呼び出しと戻り値の受け取り方が分からなかった
MyBatisを用いたJavaプロジェクトにて、MySQLサーバに設定したストアド・プロシージャを呼び出して、戻り値を得たかったのですが、 これ、といった模範例に巡り合えず、1日溶かしたので、備忘録を兼ねて、記事にします。
なるほど、完全に理解した
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="pro.eng.yui.samples.p_my_procedure"> <update id="run" statementType="CALLABLE" parameterType="P_My_Procedure"> call p_register_payment( <!-- inputs --> #{workerId}, #{paymentDate}, #{boost}, <!-- outputs --> #{success, mode=OUT, javaType=Boolean, jdbcType=NUMERIC}, #{paymentId, mode=OUT, javaType=Long, jdbcType=NUMERIC}, #{errMsg, mode=OUT, javaType=pro.eng.yui.samples.callProcWithMybatis.dto.colType.ErrMsg, jdbcType=VARCHAR} ); </update> </mapper>
@Test public void test(){ P_My_Procedure paramAndResult = new P_My_Procedure(); paramAndResult.workerId = 1234; paramAndResult.paymentDate = new Date(); paramAndResult.boost = 100; session.update(QueryId.run, paramAndResult); assertAll( () -> {assertTrue(paramAndResult.success);}, () -> {assertNull(paramAndResult.errMsg);}, () -> {assertNotNull(paramAndResult.paymentId);} ); System.out.println("paymentId is "+ paramAndResult.paymentId); }
この2つのソースファイルが、解決した状態の集大成です。
解説
まずは、XMLのmapperファイルから。プロシージャ自体は通常通りの定義をしておきます。 それに合わせて、DTO(Data-Transfar-Object)クラスを定義して、これの1インスタンスを、 パラメータの引き渡しにも、出力の受け取りにも共用します。
mapperでは、通常のパラメータマッピングに加えて、出力を受け取るパラメータに対してmode=OUT, javaType=String, jdbcType=CHAR
の要素が増えているのがポイントです。
また、SQLに対応するタグは<update>
で、見慣れない属性statementType="CALLABLE"
を付与します。
javaType
はjava.langパッケージ系の標準要素なら特段気にせず書けますが、サンプルソースの最後の要素のように、
独自定義のデータクラスを定義することもできます。
この場合、mybatis-config.xmlでtypeHandler
の指定と、Javaでのハンドリング実装が必要になります。
実装例はGitHubで公開しているconfig.xmlと、対応するJavaハンドラクラスの実装を参照してください。
続けて、呼び出すJavaプログラムの方。MyBatis利用時の通常の方法にて、SqlSession
を取得してください。
取得したSqlSessionに対して、.update("mapperNameSpace.queryId", DtoInstance)
の様式でクエリ実行を指示します。
この時プロシージャへのIN,すなわち引き渡しパラメータの値を持ったDTOクラスのインスタンスに対して、 プロシージャからのOUT,すなわち戻り値が格納されます。 上記サンプルjavaコードの10~12行目の通り、インスタンスのフィールドで戻り値が取得できます。
参照資料
上記xmlおよびjavaを含む、実行可能なJavaプロジェクトおよびMySQL構築用クエリは、北村由衣のGitHubのリポジトリ『CallProcWithMybatis』を参照ください。
この課題事項の解決に大いに寄与したウェブ情報は、英語版StackOverflowの記事『Java MyBatis stored procedure call with OUT parameters』です。こちらではJavaのDAOクラスでSQL文を実装していますが、記法が大いに参考になりました。
つれづれ
結局Google検索する時、ニッチな情報は英語ソースから得られるなぁ、という所感。 Qiitaといったまとめ記事系や、日本語版StackOverflowといったQ&A形式のサイトもありますが、 日本語で発信するという行為に価値があるのではないか、と感じます。