개요
CRUD 코드를 짜거나 보면 보통
// List<Map<String,Object>> list 라는 녀석이 넘어왔다고 가정하자
for (Map<String,Object> map : list){
// ~ 업무로직 ~
// ~ 업무로직 ~
// ~ 업무로직 ~
// 트랜잭션
insert(map);
}
라는 느낌으로 작성을 했고 작성된 것도 많이 봤다.
트랜잭션이 발생할 때마다 웹에서 db로 왔다 갔다 작업을 하는 것을 우리는 알고있다.
이 점을 염두하고 생각을 해보니까 list가 10건 30건 정도면 다행이지만 천단위를 넘어서 수만건의 데이터가 넘어온다면?
웹에서 db로 왔다갔다 하는 작업만 수만번을 반복해야되는 아주 비효율적인 상황이 발생한다.
효율적인 트랜잭션?
그렇다면 좀 더 효율적으로 어떻게 짜야될까? 생각해보니
건마다 보내는 것이 아닌 '리스트에 담고 50건, 100건이 쌓이면 그때 리스트를 넘겨 트렌잭션을 일으키는건?' 이라는 생각을 했다.
// 똑같이 List<Map<String,Object>> list 라는 녀석이 넘어왔다고 가정하자
// 트렌잭션에 사용할 객체생성
List<Map<String,Object>> tempList = new ArrayList<>();
Map<String,Object> tempMap = new HashMap<>();
for (int i=0; i<list.size(); i++){
tempMap = list.get(i);
// ~업무로직~
// ~업무로직~
// ~업무로직~
tempList.add(tempMap);
// 50건이 쌓이면 트랜잭션
if (tempList.size() == 50){
insert(tempList);
tempList = new ArrayList<>(); // tempList초기화
} else {
// tempList가 50건이 안쌓였지만 for문이 끝난경우
if (i == list.size()-1){
insert(tempList);
}
}
tempMap.clear(); // tempMap 초기화
}
이런 느낌으로 50건 100건이 쌓이면 그때 리스트를 넘겨 트랜잭션을 한 번만 일으키는 방식을 사용해보니 잘 동작한다.
뿌듯하다. 앞으로 이런 방식으로 짜야겠다.
마이바티스 foreach
해당 로직을 사용하기 위해 mapper.xml을 좀 수정해줘야된다.
1. insert
<insert id="아이디" parameterType="java.util.List" >
INSERT INTO 테이블명(
컬럼1
, 컬럼2
, 컬럼3
) VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.키1}
, #{item.키2}
, #{item.키3}
)
</foreach>
</insert>
요런 느낌으로 foreach를 추가해줘야된다.
"어? 저는 insert 할 때 시퀀스를 사용하거든요? 근데 foreach 적용하니까 에러나요!!"
<update id="아이디" parameterType="java.util.List">
INSERT INTO 테이블명 (
컬럼1,
컬럼2,
컬럼3
)
SELECT 시퀀스명.NEXTVAL
, T.*
FROM (
<foreach collection="list" item="item" index="index" separator="union all">
SELECT #{item.키1},
#{item.키2}
FROM DUAL
</foreach>
) T
</update>
컬럼1이 시퀀스를 사용하는 컬럼이라고 가정하면, 요런 느낌으로 작성하자
2. update
<update id="아이디" parameterType="java.util.List">
<foreach collection="list" index="index" item="item" separator=";" open="DECLARE BEGIN" close="; END;">
UPDATE 테이블명
SET 컬럼1 = #{item.키1},
컬럼2 = #{item.키2},
컬럼3 = #{item.키3}
WHERE 컬럼4 = #{item.키4}
</foreach>
</update>
업데이트는 요런식으로 DECLARE BEGIN END 구조를 사용하자
'개발 및 잡담 > JAVA' 카테고리의 다른 글
[JAVA] Servlet Filter를 이용하여 POST,GET 요청만 허용하고 나머지 차단하기 (0) | 2023.08.28 |
---|---|
[JAVA] SpringSecurity 에서 WebSecurityConfigurerAdapter의 extends가 안될 때 (부제: 스프링 시큐리티 POST, GET 제외 차단) (0) | 2023.08.25 |
[JAVA] 데이터를 entity 형식에 맞게 변형 (0) | 2023.04.03 |
[JAVA] Bigdecimal 크기비교 (0) | 2023.04.03 |
댓글