개발/자바

myBatis 3) 쿼리에 파라미터에 객체 전달 시 프로퍼티 찾지 못할 때

대왕판다 2023. 2. 10. 18:19

서블릿 / 스프링프레임워크 프로젝트를 오가며 바티스 쿼리 매퍼를 작성하다보니, 아래와 같은 사항들을 알게되어 정리해본다.

공식문서에서 해당 내용을 찾기 힘들었는데, 같은 문제로 애먹는분들에게 도움이 되면 좋겠다.

 

myBatis 3 매퍼 SQL 프라그먼트에 parameter 를 전달할때,

  1. 서블릿 프로젝트로 진행시, DAO에서 파라미터에 VO를 담아준다면?
    • fragment에서 받을 때 Map.property 혹은 VO.property 라고 명시/사용 해줘야한다.
    • AND title like CONCAT('%',#{searchCriteria.keyword},'%')
  1. 스프링 프레임워크 레포지토리에서 VO(DTO)를 파라미터로 넘겨줄 시 반대로 명시할 필요 없이 필드명만 입력해줘도 된다.
    • AND title like CONCAT('%',#{keyword},'%')

 

사용 예시

0. 사전조건

  • 아티클 매퍼 인터페이스와 파라미터로 전달될 VO 예시
// ArticleMapper.java

/**
 * 게시글 매퍼 인터페이스
 */
@Mapper
public interface ArticleMapper {

    /**
     * 조건에 맞는 게시글 리턴
     * @param board 게시판 종류. String substitute(${}) 를 사용하기 때문에 서비스 내에서 정해진 값만 전달
     * @return 게시글 리스트
     */
    public List<ArticleVO> selectSearchArticles(@Param("board") String board, @Param("dbLimitOffset") Integer dbLimitOffset, @Param("searchCriteria")
            SearchCriteriaVO searchCriteria);
}
// SearchCriteriaVO.class
public class SearchCriteriaVO {

  /**
         * 검색 키워드
         */
  private String keyword;

  /**
         * 게시판 ID
         */
  private Integer boardId;

  /**
         * 검색조건 시작날짜
         */
  private String startDate;

  /**
         * 검색조건 종료날짜
         */
  private String endDate;

  /**
         * 페지네이션값, 현재페이지
         */
  private Integer currentPage = 1;

  /**
         * dbLimit offset. preparedStatement 사용을 위해서는 currentPage 값으로 연산 불가능..
         */
  private Integer dbLimitOffset = 0;
}

 

1. 서블릿 프로젝트 예시

<!-- article_mapper.xml -->

<!-- 재사용을 위한 SQL 프라그먼트  -->
<sql id="searchCondition">
  <trim prefix="where (" suffix=")" prefixOverrides="AND">
    <if test="searchCriteria != null">
      AND title like CONCAT('%',#{searchCriteria.keyword},'%')
    </if>
    <if test="searchCriteria != null">
      AND created &gt;= #{searchCriteria.startDate}
      OR modified &gt;= #{searchCriteria.startDate}
    </if>
    <if test="searchCriteria != null">
      AND created &lt;= #{searchCriteria.endDate}
      OR modified &lt;= #{searchCriteria.endDate}
    </if>
  </trim>
</sql>

<!-- 실제 select 쿼리문  -->
<select id="selectSearchArticles" resultType="vo.ArticleVO">
  SELECT *
  FROM ${board}
  <include refid="searchCondition">
    <property name="searchCriteria" value="searchCriteria"/>
  </include>
  ORDER BY id DESC
</select>

위 SQL 프라그먼트 코드에서 확인할 수 있듯 #selectSearchArticles select 쿼리문에 전달 된 searchCriteira 객체의 프로퍼티를 searchCriteria.startDate와 같이 직접 명시해준 형태로 사용한다

 

2. 스프링 프레임워크 사용시

<!-- article_mapper.xml -->

<!-- 재사용을 위한 SQL 프라그먼트  -->
<sql id="searchCondition">
  <trim prefix="where (" suffix=")" prefixOverrides="AND">
    <if test="searchCriteria != null">
      AND title like CONCAT('%',#{keyword},'%')
    </if>
    <if test="searchCriteria != null">
      AND created &gt;= #{startDate}
      OR modified &gt;= #{startDate}
    </if>
    <if test="searchCriteria != null">
      AND created &lt;= #{endDate}
      OR modified &lt;= #{endDate}
    </if>
  </trim>
</sql>

파라미터로 전달 된 객체(map, VO) 속 프로퍼티와 SQL 쿼리 파라미터명을 알아서 매핑해주어 객체.프로퍼티 형태가 아닌 #{프로퍼티} 명으로만 사용해줘도된다!