Java/MyBatis

MyBatis에 인자를 넘기는 다양한 방법

Ethan Kang 2016. 11. 22. 19:43
반응형

0. 예제 테이블 구조

CREATE TABLE users (
  id          INT          PRIMARY KEY AUTO_INCREMENT,
  username    VARCHAR(40)  NOT NULL,
  email       VARCHAR(100),
  age         INT,
  created_at  TIMESTAMP    DEFAULT CURRENT_TIMESTAMP
);

1. 객체로 넘기기

1‑1. Java 코드

// User.java (Lombok 예시)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
  private Integer id;
  private String  username;
  private String  email;
  private Integer age;
}

1‑2. Mapper 인터페이스

@Mapper
public interface UserMapper {
  int insertUser(User user);
  User findById(Integer id);
}

1‑3. XML 매핑

<insert id="insertUser" parameterType="com.example.User">
  INSERT INTO users(username, email, age)
  VALUES (#{username}, #{email}, #{age})
</insert>

<select id="findById" parameterType="int" resultType="com.example.User">
  SELECT id, username, email, age, created_at
  FROM users
  WHERE id = #{id}
</select>

장점

  • IDE 자동 완성 & 컴파일 타임 타입 검증
  • 필드가 많아져도 메서드 시그니처가 깔끔

주의사항

  • 같은 DTO를 여러 쿼리에서 재사용할 때 N+1 필드 문제(필요 없는 칼럼 포함) 발생 가능
  • 필드명이 컬럼명과 다른 경우 resultMap을 별도로 정의해야 함

2. HashMap<String, Object>로 넘기기

2‑1. 자바 호출부

Map<String, Object> params = new HashMap<>();
params.put("username", "eunseok");
params.put("minAge", 25);

List<User> list = userMapper.findByNameAndMinAge(params);

2‑2. XML 매핑

<select id="findByNameAndMinAge"
        parameterType="hashmap"
        resultType="com.example.User">
  SELECT *
  FROM users
  WHERE username = #{username}
    AND age      &gt;= #{minAge}
</select>

장점

  • 동적 칼럼/조건 조합이 필요할 때 유연
  • 별도 DTO 생성 없이 빠르게 시도 가능

단점

  • 타입 안전성 없음 (런타임 오류, 오타 찾기 어려움)
  • 컬럼 수가 많아질수록 가독성 급감

3. 원시형(Primitive) 또는 단일 값으로 넘기기

3‑1. 하나의 파라미터만 필요할 때

User user = userMapper.findByUsername("eunseok");
<select id="findByUsername"
        parameterType="string"
        resultType="com.example.User">
  SELECT *
  FROM users
  WHERE username = #{value}
</select>

#{value} 또는 #{_parameter} 로 이름 없이 참조합니다.
Tip: 파라미터 이름이 딱 하나면 어떤 타입이든 #{value}로만 접근 가능합니다.


3‑2. 둘 이상의 프리미티브를 넘길 때 @Param 활용

@Select("""
  SELECT *
  FROM users
  WHERE username = #{username} AND age >= #{age}
  """)
List<User> search(@Param("username") String username,
                  @Param("age")      int    minAge);

장점

  • 불필요한 DTO 생성 없이 심플

단점

  • 파라미터 수가 조금만 늘어나도 메서드 시그니처가 장황해짐
  • 재사용/테스트 불리함

4. 보너스: 컬렉션(List·배열) 넘기기

List<Integer> ids = List.of(1, 3, 5);
List<User> users = userMapper.findByIds(ids);
<select id="findByIds" parameterType="list" resultType="com.example.User">
  SELECT *
  FROM users
  WHERE id IN
  <foreach collection="list"
           item="id"
           separator=","
           open="("
           close=")">
    #{id}
  </foreach>
</select>

5. 정리: 언제 무엇을 쓸까?

상황 추천 방식 비고
대부분의 CRUD 객체 타입 안전 & 유지보수 용이
동적 조건 or 칼럼이 바뀔 때 Map 빠른 프로토타이핑·Ad‑hoc 쿼리
단일 값(키 조회 등) 프리미티브 성능·단순성
2~3개의 단순 조건 프리미티브 + @Param DTO 만들려니 애매할 때
IN 절 배치 조회 컬렉션(List/배열) <foreach> 필수

6. 참고 자료

  1. opens.kr — 「MyBatis parameterType 정리」
  2. MyBatis 공식 문서: User Guide → Parameters
반응형