[Mybatis] Procedure 호출

*MyBatis 에서 Procedure 호출

 - 자주 사용될 쿼리문이나 업무로직을 미리 만들어두고, 필요한 곳에서 사용하기위해.

-procedure 작성법)

 create or replace procedure 프로시저명( 매개변수 in 데이터형,,,,,, 매개변수 out 데이터형,,, )

 is

  -- 변수선언, cursor 선언, record 선언, table 선언

 begin

  -- 업무로직을 처리 ( 쿼리문 + 제어 + 연산 )

 exception

   --예외처리코드

 end ;

 /

 -MyBatis에는 procedure호출할때  <select> 만 사용한다.

 -statementType속성을  “CALLABLE”로 설정한다.

  

  사용예)

  <select id=“아이디parameterType=“” statementType=“CALLABLE”>

    { call 프로시저명( #{ getter,mode=파라메터의종류,jdbcType=java.sql.Types의 데이터형} ,,, )  }   

  </select>

 -MyBatis Handler에서 

   ss.selectOne(“아이디” , DTO);

 

//insert할 값은 getter method에서 반환된 값으로 insert를 수행하고,

  out parameter 값은 setter method가 호출되어 처리된 결과 값이 할당

*DTOsetter method 해당되는 getter method를 호출하면

프로시저에서 처리된 결과를 받을 수 있다.


 

*insert

 -값을 저장할 수 있는 DTO생성

 public class EmpDTO{

   private int empno, sal, cnt;

   private String ename, job, msg;

 }

-XxxMapper.xml

  <select id=“아이디parameterType=“EmpDTOstatementType=“CALLABLE”>

   {

     call insert_cp_emp(#{ empno,mode=IN,jdbcType=NUMERIC } ,

                              #{ ename,mode=IN,jdbcType=VARCHAR },

                              #{ job,mode=IN,jdbcType=VARCHAR },

                             #{ sal,mode=IN,jdbcType=NUMERIC } ,

                             #{ cnt,mode=OUT,jdbcType=NUMERIC } ,

                             #{ msg,mode=OUT,jdbcType=VARCHAR }

                             )

   }

  </select>

 -Handler를 실행

 ss.selectOne(“아이디”, empDTO );

 -프로시저 실행 결과 얻기

  empDTO.getCnt();  empDTO.getMsg();

 


*select procedure

 - cursor 사용 ( SYS_REFCURSOR 사용 커서의 제어권을 넘겨주는 커서)

 

*암시적 커서( sql )

  -insert, udpate, deleted의 수행 행수를 반환하는 커서.

  -개발자가 커서를 선언하지 않고, 쿼리문이 실행되면서 자동으로 생성되는 커서.

  -커서명은  SQL이고, 속성 %ROWCOUNT 만 존재.

*명시적커서

  -여러 행을 조회할 때 사용하는 커서. ( PL/SQL에서는 select문으로 한 행 만 조회가능)

  -개발자가 커서를 선언하고 사용하는 커서.

  - 프로시저 안에서 여러 행을 조회하는 커서와 제어권을 반환하는 커서 두가지 제공.

 

CURSOR 선언:

선언, 열기, 인출, 닫기의 생명주기를 가지는 커서

선언 : cursor 커서명 is select쿼리문

open : open 커서명

fetch :  반복문 사용

 loop

   fetch 커서명 is 변수명,,,,;

 end loop;

close : close 커서명

 

SYS_REFCURSOR:

 -SQLPlus에서 REFCURSOR바인드 변수로

   선언하고 커서를 저장하여 프로시저

  외부에서 조회 결과를 사용.

-java에서는 ResultSet을 제어권을 받는다.

 

*사용법)

-프로시저선언)

 create or replace procedure 프로시저명( 커서명 out SYS_REFCURSOR)

 is

 begin

    open 커서명 for select쿼리문,,,

 end ;

-XxxMapper.xml

 HashMap 필요.

1.Hashmap정의( MyBatis Framework에서는 java.util.HashMap클래스를 hashmap이라는 객체로 제공)

  <resultMap id=“아이디” type=“hashmap”/>

2.프로시저 호출

  <select id=“아이디statementType=“CALLABLE”>

    { call 프로시저명( #{map,mode=IN,jdbcType=java.sql.Types},

                        #{map,mode=OUT,jdbcType=java.sql.ResultSet,resultMap=resultMap아이디} )}

  </select>

-MyBatis Handler

 1. 프로시저에 전달할 값과 Procedure 에서 처리한 결과를 저장할 Map생성

   Map<String, Object> map=new HashMap<String,Object>();

 2. Procedure에서 사용할 in parameter값을 설정.

    map.put( “map”, );

 3. Procedure 호출

   ss.selectOne(“아이디”, map);

 4.조회결과 받기

  List<Map<String,Object>> data=map.get(“”);


 

*1. procedure 생성

2. procedure 호출( Mapper.xml )

 2-1.resultMap 선언 : 조회된 결과를 저장하여 반환하기 위한 Map.

  <resultMap id=“carMap” type=“hashmap”/>

 2-2.procecure 호출

  <select id=“carSelectstatementType=“CALLABLE”>

   {

    call select_car2( #{ maker,mode=IN,jdbcType=VARCHAR },

                         #{ selectCar, mode=OUT,jdbcType=CURSOR,javaType=java.sql.ResultSet,resultMap=carMap }, //결과를 map저장

                         #{ errm, mode=OUT,jdbcType=VARCHAR,resultMap=carMap })

   }

  </select>

3. Handler에서 사용.

  3-1. Map 선언

   Map<String,Object> map=new HashMap<String,Object>();

  3-2. map에 키로 값을 설정

   map.put(“maker”,”현대”);

  3-3.실행

   ss.selectOne(“carSelect”, map );

  3-4. map에 저장된 결과 얻기

    List<Map<String,Object>> list=(List<Map<String,Object>>)map.get(“selectCar”);

  4-4.

  List<XxxDomain> carList=new ArrayList<XxxDomain>();

  XxxDomain xd=null;

  for(Map<String,Object> recordMap : list){

   xd=new XxxDomain(); 

    xd.setter(recordMap.get(“컬럼명”) );

   }

  

-숫자 : BigDecimal

 xd.setter(  ((BigDecimal)recordMap.get(“PRICE”)).intValue() );

-문자열 : String

 xd.setter(  (String)recordMap.get(“MODEL”)  );

-날짜 : Domain클래스에 Timestamp

 xd.setter( (Timestamp)recordMap.get(“HIREDATE”) );

-날짜 : Domain클래스에 Date

 xd.setter(  new Date( ((Timestamp)recordMap.get(“HIREDATE”) ).getTime() ) );