데이터베이스

[MyBatis] foreach

삼록이 2025. 10. 29. 15:35

<foreach>란?

:마이바티스에서 <foreach>는 배열,리스트,맵 등 반복 가능한 컬렉션 데이터를 SQL의 IN절이나 VALUE,SET,WHERE 절 등 에반 복되는 SQL패턴이 필요한 곳에서 사용된다.

 

예를 들어, 아래와 같은 자바 코드가 있다.

List<Integer> ids = List.of(1, 2, 3);

 

이 리스트를 동적으로 받아 아래와 같은 SQL문을 마이바티스 쓰고 싶다.

하지만 이는 틀린 문법이다. MyBatis에서 #{ }는 값 하나만 바인딩하기 때문이다

SELECT * FROM user WHERE id IN #{ids};

이 때 사용할 수 있는 것이 foreach다.

SELECT * FROM user WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close = ")">
#{id}
</foreach>

 

이렇게 하면 SQL은 SELECT * FROM user WHERE id IN (1,2,3)으로 바인딩 해준다.

 

*문법

<foreach
  collection="컬렉션명"
  item="각 항목 이름"
  index="인덱스 변수명"
  open="시작문자"
  close="끝문자"
  separator="구분자">
  #{item}
</foreach>

 

*collection에는 매개변수로 DTO를 사용했을 경우 내부의 컬렉션필드 이름을 써야한다

인서트 문에서 사용할 시 아래처럼도 사용이 가능하다.

<insert id="insertUsers" parameterType="list">
  INSERT INTO user (name, age)
  VALUES
  <foreach collection="list" item="user" separator=",">
    (#{user.name}, #{user.age})
  </foreach>
</insert>

 

이러면 내부적으로 아래와 같은 형태로 바인딩 되어 SQL문이 날라간다.

INSERT INTO user (name, age)
VALUES ('홍길동', 20), ('김철수', 25), ('이영희', 30);

 

 


이번엔 EXISTS 문에서 foreach를 활용할 수 있는 예시에 대해 알아보자

 

아래처럼 두 개의 테이블이 있다고 해보자.

  • project 테이블 : 프로젝트 기본 정보에 관한 테이블
  • project_tag 테이블 : 프로젝트에 연결된 기술 해시태그 테이블

 

 

이 때 사용자가 화면에서 체크한 해시태그를 가진 프로젝트를 필터링하고 싶다면

사용자가 체크한 해시태그값을 List<String>타입의 list로 받을 수 있다.

이때 list에는 'Python'과  'AWS'값이 들어있다 치자.

그러면 아래처럼 매퍼파일에 작성한다면

<select id="selectProjectsByTags" parameterType="list" resultType="Project">
  SELECT
      p.project_id,
      p.project_name
  FROM project p
  WHERE 1=1
  <if test="list != null and list.size() > 0">
    <foreach collection="list" item="tagName">
      AND EXISTS (
        SELECT 1
        FROM project_tag pt
        WHERE pt.project_id = p.project_id
        AND pt.tag_name = #{tagName}
      )
    </foreach>
  </if>
  ORDER BY p.project_id
</select>

리스트에 있는 'Python'과 'AWS값이 동적으로 바인딩 되어 아래의 SQL문이 날아가게 된다.

SELECT p.project_id, p.project_name
FROM project p
WHERE 1=1
  AND EXISTS (
    SELECT 1 FROM project_tag pt
    WHERE pt.project_id = p.project_id
    AND pt.tag_name = 'Python'
  )
  AND EXISTS (
    SELECT 1 FROM project_tag pt
    WHERE pt.project_id = p.project_id
    AND pt.tag_name = 'AWS'
  )
ORDER BY p.project_id;

 

 그 결과, Python과 AWS 해시태그 값을 가진 프로젝트를 조회해올 수 있다.