Database/MS-SQL

MSSQL) MyBatis와 프로시저 update/insert 사용시 결과 값 받기. -1이 반환될때, MyBatis + Procedure

luana_eun 2023. 10. 26. 11:12
728x90

어느때와 같이 쿼리문을 수정하고 있는데, 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와 프로시저를 자유롭게 이용하기 완성

 

이 글이 도움이 되었다면 "공감" 부탁드립니다 :)

728x90