Contents
see ListMyBatis Map이나 Bean 없이 2개 이상 파라미터 전달
MyBatis에서 Map이나 DTO Bean을 만들지 않고 여러 파라미터를 Mapper 메서드에 전달하는 방법입니다. 간단한 쿼리에서 불필요한 클래스 생성을 줄일 수 있습니다.
언제 사용하나요?
- 간단한 조회에서 2-3개 파라미터 전달
- DTO 클래스 생성이 과한 경우
- 페이징 처리 (offset, limit)
- 범위 검색 (startDate, endDate)
방법 1: @Param 어노테이션 (권장)
// Mapper 인터페이스
@Mapper
public interface UserMapper {
// 단일 파라미터는 @Param 생략 가능
User findById(Long id);
// 2개 이상은 @Param 필수
User findByEmailAndStatus(
@Param("email") String email,
@Param("status") String status
);
// 페이징
List<User> findAllWithPaging(
@Param("offset") int offset,
@Param("limit") int limit
);
// 날짜 범위
List<Order> findByDateRange(
@Param("startDate") LocalDate startDate,
@Param("endDate") LocalDate endDate,
@Param("status") String status
);
}
XML Mapper에서 사용
<!-- @Param으로 지정한 이름 그대로 사용 -->
<select id="findByEmailAndStatus" resultType="User">
SELECT * FROM users
WHERE email = #{email}
AND status = #{status}
</select>
<!-- 페이징 -->
<select id="findAllWithPaging" resultType="User">
SELECT * FROM users
ORDER BY created_at DESC
LIMIT #{limit} OFFSET #{offset}
</select>
<!-- 조건부 파라미터 -->
<select id="findByDateRange" resultType="Order">
SELECT * FROM orders
WHERE 1=1
<if test="startDate != null">
AND order_date >= #{startDate}
</if>
<if test="endDate != null">
AND order_date <= #{endDate}
</if>
<if test="status != null and status != '">
AND status = #{status}
</if>
</select>
방법 2: param1, param2 사용
// @Param 없이 순서로 접근
List<User> findByAgeRange(int minAge, int maxAge);
<!-- XML에서 param1, param2로 접근 -->
<select id="findByAgeRange" resultType="User">
SELECT * FROM users
WHERE age BETWEEN #{param1} AND #{param2}
</select>
<!-- 또는 arg0, arg1 (비권장) -->
<select id="findByAgeRange" resultType="User">
SELECT * FROM users
WHERE age BETWEEN #{arg0} AND #{arg1}
</select>
<!-- param1, param2는 가독성이 낮아 @Param 권장 -->
방법 3: Map 사용
// Map으로 전달
List<User> findByConditions(Map<String, Object> params);
// 호출
Map<String, Object> params = new HashMap<>();
params.put("status", "ACTIVE");
params.put("minAge", 20);
params.put("maxAge", 30);
List<User> users = mapper.findByConditions(params);
<!-- XML -->
<select id="findByConditions" resultType="User">
SELECT * FROM users
WHERE status = #{status}
AND age BETWEEN #{minAge} AND #{maxAge}
</select>
INSERT/UPDATE에서 사용
// 여러 파라미터로 UPDATE
int updateStatus(
@Param("id") Long id,
@Param("status") String status,
@Param("updatedBy") String updatedBy
);
<update id="updateStatus">
UPDATE users
SET status = #{status},
updated_by = #{updatedBy},
updated_at = NOW()
WHERE id = #{id}
</update>
// 조건부 INSERT
int insertIfNotExists(
@Param("email") String email,
@Param("name") String name
);
복잡한 조건 처리
<!-- 동적 IN 절 -->
List<User> findByIds(@Param("ids") List<Long> ids);
<select id="findByIds" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach collection="ids" item="id"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
<!-- 여러 파라미터 + 리스트 -->
List<Order> findOrders(
@Param("userId") Long userId,
@Param("statuses") List<String> statuses
);
<select id="findOrders" resultType="Order">
SELECT * FROM orders
WHERE user_id = #{userId}
AND status IN
<foreach collection="statuses" item="status"
open="(" separator="," close=")">
#{status}
</foreach>
</select>
주의사항
- 파라미터가 3개 이상이면 DTO 클래스 권장
- @Param 이름과 XML 변수명 정확히 일치해야 함
- null 값 처리를 위한 조건문 추가 필요
- MyBatis 3.x 이상에서 @Param 사용 가능