松山事務所の石丸です。
MyBatisでOracleのストアドプロシージャ・ストアドファンクションを実行するのに苦労したので記事にしました。
MyBatisのバージョンは3.4(SpringBootプロジェクトでmybatis-spring-boot-starter:1.3.1)になります。
ストアドプロシージャの呼び出し方
例えば次のようなプロシージャを呼び出す場合。
1
2
3
4
5
6
|
HogeProcedure(
PARAMETER1 IN NUMBER,
PARAMETER2 IN VARCHAR2,
RESULT1 OUT NUMBER,
RESULT2 OUT VARCHAR2
)
|
モデルクラスを作成せずにMapでIN/OUTを受け取ってみます。
1
|
void HogeProcedure(Map parameters);
|
mapperの定義では statementTypeに "CALLABLE"
を指定します。
OUTパラメータを受け取るために、普段は省略している mode を指定します。
1
2
3
4
5
6
7
8
|
<select id="HogeProcedure" statementType="CALLABLE">
{call HogeProcedure(
#{PARAMETER1, mode=IN, jdbcType=INTEGER}
,#{PARAMETER2, mode=IN, jdbcType=VARCHAR}
,#{RESULT1, mode=OUT, jdbcType=INTEGER}
,#{RESULT2, mode=OUT, jdbcType=VARCHAR}
)}
</select>
|
呼び出し例
1
2
3
4
5
6
7
|
Map parameters = new HashMap();
parameters.put("PARAMETER1", 1);
parameters.put("PARAMETER2", "param2");
mapper.HogeProcedure(parameters);
Integer result1 = (Integer)parameters.get("RESULT1");
String result2 = (String)parameters.get("RESULT2");
|
INパラメータだけ設定してプロシージャを呼び出すと、OUTパラメータが設定されて返ってきます。
ストアドファンクションの呼び出し方
例えばこんなファンクションを呼び出す場合。
1
2
3
4
|
HogeFunction(
IN_PARAMETER IN NUMBER,
OUT_PARAMETER OUT VARCHAR2
) RETURN NUMBER
|
ここで気を付けるのは戻り値の型です。
呼び出すストアドファンクションはNUMBERを返しますが、その戻り値はparametersで受け取るため、mapperの戻り値はvoidです。
1
|
void HogeFunction(Map parameters);
|
mapperの定義ではcallの結果をRESULTで受けとるように記述します。
1
2
3
4
5
6
|
<select id="HogeFunction" statementType="CALLABLE">
{#{RESULT, jdbcType=INTEGER, mode=OUT} = call HogeFunction(
#{IN_PARAMETER, mode=IN, jdbcType=INTEGER}
,#{OUT_PARAMETER, mode=OUT, jdbcType=VARCHAR}
)}
</select>
|
(今ふと思ったのですが、もしかしたら resultType="java.lang.Integer"
にしたらRESULTへの代入なしにInteger返してくれたりして。。。)
呼び出し例
1
2
3
4
5
6
|
Map parameters = new HashMap();
parameters.put("IN_PARAMETER", 1);
mapper.HogeFunction(parameters);
Integer result = (Integer)parameters.get("RESULT");
String outParameter = (String)parameters.get("OUT_PARAMETER");
|
mapなのが嫌だ
せっかく型のある言語なのでちゃんとモデルクラスを定義してみます。
例えばこんなプロシージャ。
1
2
3
4
5
6
|
HogeProcedure(
PARAMETER1 IN NUMBER,
PARAMETER2 IN VARCHAR2,
RESULT1 OUT NUMBER,
RESULT2 OUT VARCHAR2
)
|
IN/OUTを1つのクラスで渡して受け取る
1
2
3
4
5
6
|
class ParameterAndResult {
Integer PARAMETER1;
String PARAMETER2;
Integer RESULT1;
String RESULT2;
}
|
1
|
void HogeProcedure(ParameterAndResult parameterAndResult);
|
1
2
3
4
5
6
7
8
|
<select id="HogeProcedure" statementType="CALLABLE">
{call HogeProcedure(
#{PARAMETER1, mode=IN, jdbcType=INTEGER}
,#{PARAMETER2, mode=IN, jdbcType=VARCHAR}
,#{RESULT1, mode=OUT, jdbcType=INTEGER}
,#{RESULT2, mode=OUT, jdbcType=VARCHAR}
)}
</select>
|
呼び出し例
1
2
3
4
5
6
7
|
ParameterAndResult parameterAndResult = new ParameterAndResult();
parameterAndResult.PARAMETER1 = 1;
parameterAndResult.PARAMETER2 = "param2";
mapper.HogeProcedure(parameterAndResult);
Integer result1 = parameterAndResult.RESULT1;
String result2 = parameterAndResult.RESULT2;
|
IN/OUTをそれぞれを別のクラスにしてみる
1
2
3
4
5
6
7
8
9
|
class Parameter {
Integer PARAMETER1;
String PARAMETER2;
}
class Result {
Integer RESULT1;
String RESULT2;
}
|
複数オブジェクトを渡す場合は、オブジェクトを区別するために@Paramで名前を付けます。
1
|
void HogeProcedure(@Param("IN") Parameter parameter, @Param("OUT") Result result);
|
mapper.xml側では@Paramで指定された名前を使用してオブジェクトが区別できます。
1
2
3
4
5
6
7
8
|
<select id="HogeProcedure" statementType="CALLABLE">
{call HogeProcedure(
#{IN.PARAMETER1, mode=IN, jdbcType=INTEGER}
,#{IN.PARAMETER2, mode=IN, jdbcType=VARCHAR}
,#{OUT.RESULT1, mode=OUT, jdbcType=INTEGER}
,#{OUT.RESULT2, mode=OUT, jdbcType=VARCHAR}
)}
</select>
|
呼び出し例
1
2
3
4
5
6
7
8
|
Parameter in = new Parameter();
in.PARAMETER1 = 1;
in.PARAMETER2 = "param2";
Result out = new Result();
mapper.HogeProcedure(in, out);
Integer result1 = out.RESULT1;
String result2 = out.RESULT2;
|