메이블
70
2020-11-20 17:04:14
1
217

ibatis bulk insert (forall)


안녕하세요. 엑셀을 업로드해서 오라클 DB에 올리는 작업을 하고 있는데,

지금하는 엑셀은 데이터 4만개를 전부 올려야하는 상황입니다.


데이터를 읽어서 올리는 방식은

한 행의 열 (A,B,C) 마다의 값을 MAP에 담고 ex) map.put("A", "가나다라") ...

MAP을 LIST에 담아서 한 행의 정보를 담아서 여러 행(리스트)를 다시 MAP에 담아서 DAO에 넘깁니다.

MAP1 - LIST - MAP2 구조인데, 기존의 엑셀들은 올려야하는 행이 많지 않아서 INSERT ALL을 사용하여 INSERT 하였습니다.


<insert id="insert_excel" parameterClass="java.util.HashMap">
		INSERT ALL
		<iterate property = "excelContent" conjunction = " ">
			INTO $tableName$ (
			<iterate  property="cols" conjunction=",">
       			  $cols[]$
   			</iterate>
			) VALUES (
       		          #excelContent[].A#,
       		          #excelContent[].B#,
       		          #excelContent[].C#
       		        )
   		</iterate>
   		SELECT * FROM DUAL
</insert>


이런 식으로 MAP1에 테이블명과 컬럼명들(배열), 엑셀데이터(리스트-맵)을 담아주어서 INSERT 하였습니다.


그런데 4만 행의 엑셀을 위처럼 처리하니, 시간도 오래걸리고 오라클 오류가 떠서 찾아보니까

최대 천개까지만 처리가능하고 그 이후에는 배치나 벌크인서트를 해야되는 것 같아서 bulk insert를 해보려고 했는데, 프로시저를 사용해보지 않아서.. 대충 구조는 알겠는데 변수들을 어떻게 넣어줘야할지 고민입니다.

ibatis쪽에서 parameterMap도 해줘야하는데 MAP1 - LIST - MAP2 라서.. 여기서도 어떻게 해야할지ㅜㅜ..



우선 ibatis sql 쪽입니다.

<parameterMap id="proc_param" class="HashMap">
		<parameter property="tableName" javaType="java.lang.String" jdbcType="" mode="IN"/>
		<parameter property="cols" javaType="" jdbcType="" mode="IN"/>
		<parameter property="excelContent[].A" javaType="java.lang.String" jdbcType="NUMBER" mode="IN"/>
		<parameter property="excelContent.B" javaType="java.lang.String" jdbcType="NUMBER" mode="IN"/>
		<parameter property="C" javaType="java.lang.String" jdbcType="NUMBER" mode="IN"/>
</parameterMap>

<procedure id="call_proc" parameterMap="proc_paramp">
		<![CDATA[
			{ CALL EXCEL_PROC(tableName, cols, ...) }
		]]>
</procedure>

parameterMap에 list - map을 어떻게 담을지도 모르겠고..리스트를 넘겨야하는지 리스트 안의 맵을 넘겨야하는지도 모르겠습니다. 넘긴다면 어떻게 넘겨야할지..



CREATE TYPE array_string AS TABLE OF VARCHAR2 (50);     -- string 배열 type 선언

create or replace PROCEDURE EXCEL_PROC(
table_name IN VARCHAR2, cols IN array_string, excelContent.A IN ...,
... ) BEGIN FORALL i IN 1 .. (??) INSERT INTO table_name( FOR j IN 1 .. cols.COUNT LOOP DBMS_OUTPUT.put_line(cols(i)); --cols(i) END LOOP; ) VALUES ( excel(i).A, excel(i).B, ... ); END;


일단 프로시저 구조는 이렇게 작성했는데.. insert into 에서 cols배열 값들을 나열할때 저렇게 해도 될까요..?

FORALL에서 반복 횟수도 리스트의 개수만큼 돌려야하는데 저 부분은 행 개수를 MAP1에 담아서 tableName처럼 같이 넘겨줘서 해야할 것 같고..

VALUES에 리스트(i).키 부분도 어떻게 넣어줘야하는지.. 모르겠습니다ㅜㅜ



정리하자면

1. ibatis 쪽에서 어떻게 변수를 받아와야할까요?

+) parameterMap을 쓰려면 VO를 사용해야하지 않나요? 저는 맵으로 넘겨서 사용했어서 VO없이 하고싶은데.. 다른 방법도 있을까요? 프로시저 검색하면 파라미터맵만 나와서요..


2. 프로시저에 변수들을 어떻게 작성해야할까요..?

+) tableName이나 cols 는 그냥 명시해줘도 되는데 전에는 값을 받아서 했으니 그냥 그렇게 해보고 싶은거라서 이렇게 해보는거고, 변수들이랑 value에 넣을 부분을 어떻게 해야할지가 문제입니다.


설명을 잘 못해서 이해가 잘 되실런지..변수를 사용할 방향을 못잡겠어서 질문드립니다ㅜㅜ!

0
  • 답변 1

  • 메이블
    70
    2020-11-20 17:13:07

    parameterMap 하지 않고 기존에 했던 방식처럼 MAP1의 값을 넣어서 써도 될 것 같은데 그럼 리스트 이름을 넘겨서 프로시저 안에서 배열 받은 것처럼 리스트를 받아서 사용하면 될까요..

  • 로그인을 하시면 답변을 등록할 수 있습니다.