MSSQL) MyBatis와 프로시저 update/insert 사용시 결과 값 받기. -1이 반환될때, MyBatis + Procedure
어느때와 같이 쿼리문을 수정하고 있는데, insert/update문에서 계속 -1을 반환하는 현상을 만났다.
MyBatis에서 insert/update문은 성공시 1 또는 반영된 컬럼수를 반환하고, 실패시 0을 반환하기에
결과값이 1이상이면 성공, 0이면 실패로 구분하여 판단했었는데,
DB에 결과가 잘 반영되어 성공했는데도 계속 -1을 반환했다.
일반쿼리와 다른점은 바로 프로시저를 호출한다는 것이었다.
문제였던 코드
<update id="saveBoard" parameterType="java.util.Map">
DECLARE @result int
SET @result = 0
EXEC 프로시저명
#{title}
, #{content}
, @result output
</update>
*output : 데이터를 처리한 후 결과 값을 받는 파라미터.
처리 후 결과 값을 output 지정한 파라미터에 담아서 반환한다.
원인
MyBatis의 update/insert시 프로시저 호출시 프로시저 내에서 어떻게 돌아가고있는지 모르기에 그 반환값을 받지 못한다.
해결방법
1. update가 아닌, select로 변경하기
MyBatis에서 직접 업데이트 쿼리문을 작성하는 경우, 결과값을 int로 받지만,
프로지서를 호출하는경우, 프로시저가 실행한 결과를 받아와야 하므로 결과적으로 MyBatis입장에서는 받는 입장이기에
select로 변경해야한다.
* insert/update의 경우는 디폴트 resultType이 int여서 따로 적을 필요가 없었지만,
select로 변경하면 resultType을 지정해줘햐한다. 빼먹지 말기!
<select id="saveBoard" parameterType="java.util.Map" resultType="int">
DECLARE @result int
SET @result = 0
EXEC 프로시저명
#{title}
, #{content}
, @result output
</select>
2. 파라미터를 객체로 넘기고, 객체로 받기.
1) 테이블 컬럼명과 같이 VO(DAO,DTO)를 생성한다.
이때, 테이블 컬럼에는 없는, 쿼리 결과값을 받을 변수도 추가로 선언해야 한다. 나는 테스트로 임의로 result로 했음.
각 변수의 get, set도 있어야 한다.
public class AddProdVo {
private String title;
private String content;
private int result; // 쿼리 결과값을 받을 파라미터
// getter, setter 추가
}
2) 파라미터 값 세팅
원래라면 프론트에서 가져온 값을 controller에서 객체로 받으면 자동으로 값이 세팅되지만,
나는 잠깐 테스트만 해볼거라 직접 값을 넣어줬다.
AddProdVo ap = new AddProdVo();
@Override
public int saveBoard(Map<String, Object> paramMap) throws SQLException, Exception {
// 테스트를 위해 받은 파라미터가 아닌, 객체에 직접 값 넣기
ap.setTitle("테스트제목");
ap.setContent("테스트내용");
ap.setResult(-2); // 프로시저 결과 값을 받을 result에 테스트를 위해 -2로 셋팅
int res = testMyTestDao.testUpdateService(ap);
System.out.println("실행 후 결과: " + ap.getResult());
return null;
}
3) MyBatis에서 프로시저 호출
* statementType="CALLABLE" : 프로시저에서 out로 지정한 값들이 파라미터 map에 담긴다.
<update id="saveBoard" statementType="CALLABLE" parameterType="com.test.mytest.myevent.vo.AddProdVo">
EXEC 프로시저명
#{title}
,#{content}
,#{result, mode=OUT, jdbcType=INTEGER}
</update>
프로시저 내용
ALTER PROCEDURE [dbo].[프로시저명]
@title VARCHAR(100),
@Content VARCHAR(10),
@result INT OUTPUT -- output 선언
BEGIN
DECLARE @uRes INT;
SET @uRes = 0;
SET @result = 0;
--생략--
BEGIN TRAN
UPDATE 테이블명 SET
title = @title
, content = @content
WHERE boardNum = 10
SET @uRes = @@ERROR;
END
IF @uRes = 0
BEGIN
SET @result = 1; -- 성공시 반환값
COMMIT TRAN;
END ELSE
BEGIN
SET @result = -1; -- 실패시 반환값
ROLLBACK TRAN;
END;
MyBatis와 프로시저를 자유롭게 이용하기 완성
이 글이 도움이 되었다면 "공감" 부탁드립니다 :)