Mybatis - foreach
이전에 작성했던 포스트중에 INSERT INTO SELECT 에 대해 다뤘던적이 있다.
- INSERT INTO SELECT
해당 방법은 INSERT를 할 때 기존에 있던 데이터들과 같은 값들을 넣을때 값을 조회하면서 INSERT 하는 다중 INSERT 방식이었다.
하지만 매번 다른 값이 들어가야하는 다중 INSERT 를 해야한다면? 그 값은 DAO를 통해서 넘어온다면?
일반적으로 생각하는 방법은 다음과같이 Java단에서 List의 forEach 문법을 이용하여 INSERT 함수를 반복 호출하는것이다.
@Override
public void insertUserList(List<User> users) {
for (User user : users) {
insertUser("insertUser", user);
}
}
<insert id ="insertUser" parameterType="User">
INSERT INTO User
(user_id
, user_name
, user_passwd
, user_note)
VALUES
(#{userId}
,#{userName}
,#{userPasswd}
,#{userNote})
</insert>
What is problem?
생각해보면 코드도 깔끔하고 의미가 명확하여 좋은것같다. 하지만 이 작업을 수행하기 위해서는 예를들어 만약 1000명의 User를 삽입해야 한다면 다음과 같은 작업이 1000번 일어날 것이다.
[ DAO 함수호출 - Mapper id 검색 - DB 오픈 - Query 수행 ] x 1000
사실 굵직한 작업으로 많이 간소화해서 그렇지 이거보다 더 많은 작업이 이루어지게 된다. 위에 프로세스에서 오로지 Query 수행만 1000번하게 할 수 없을까?
Mabatis - foreach
Mybatis에서 제공하는 문법중 foreach를 이용하여 다음과 같이 바꿔보았다.
@Override
public void insertUserList(List<User> users) {
insertUser("insertUsers", users);
}
<insert id ="insertUsers" parameterType="User">
<foreach item="user" index="index" collection="users">
INSERT INTO User
(user_id
, user_name
, user_passwd
, user_note)
VALUES
(#{user.userId}
,#{user.userName}
,#{user.userPasswd}
,#{user.userNote})
</foreach>
</insert>
이렇게 하면 위에서 정의한 프로세스중 Query 수행만 1000번 돌아가기 떄문에 앞선 방법보다 성능이 훨씬 빠르다.
foreach는 INSERT 뿐만 아니라 SELECT 시 에도 쓰인다.
user_type이라는 컬럼이 있고 해당 값이 특정한 값일때만 조회를 해야하고 List를 통해서 넘어올 때 다음과 같이 mapper를 작성해주면 된다.
<select id="xxx" parameterType="User" resultType="User">
SELECT
*
FROM
user
WHERE
user_type IN
<foreach item="user" index="index" collection="users" open="(" separator="," close=")">
#{user.userType}
</foreach>
</select>
위와 같이 foreach를 작성하면 결과는 다음과 같이 나온다
user_type IN
("admin", "designer", "normal")
Conclusion
mybatis의 foreach를 이용하면 쟈바단에서의 퍼포먼스 시간을 줄일 수 있다. 만약 한번의 INSERT 후에 제대로 값이 들어갔는지 확인하여 제대로 안들어갔을때 Rollback 시키기 위해서는 처음 일반적으로 Java단에서 호출하는 방법을 이용해야 할 것이다.
결국, Database 에서 처리하기 부담스러운 작업은 Java 단에서하고 Database 로도 커버가 가능한 작업은 Database 에게 맡기는 고민을 항상 하면서 작업을 해야할 것같다.