MyBatis는 SQL을 XML에 편리하게 작성할 수 있고 동적 쿼리를 편리하게 작성할 수 있는 SQL Mapper 기술로 공식 사이트에 사용법이 잘 나와있다.

 

 

application.properties

#MyBatis
# 타입 정보를 사용할 때 패키지 경로 생략 가능, 지정한 패키지와 그 하위 패키지가 자동으로 인식
mybatis.type-aliases-package=hello.itemservice.domain
# 언더바 -> 카멜 자동 변경
mybatis.configuration.map-underscore-to-camel-case=true
# MyBatis 실행 쿼리 로그 확인
logging.level.hello.itemservice.repository.mybatis=trace
# resources/mapper 를 포함한 하위 폴터 XML을 XML 매핑 파일로 인식
mybatis.mapper-locations=classpath:mapper/**/*.xml

 

@Mapper

스프링 부트가 애플리케이션 로딩 시점에 @Mapper가 붙은 인터페이스를 동적 프록시로 구현체를 생성하고 스프링 빈으로 등록하기 때문에 인터페이스 만으로 XML의 데이터를 찾아서 호출할 수 있고 매퍼 구현체는 MyBatis에서 발생한 예외를 스프링 예외 추상화인 DataAccessException으로 변환해준다.

@Mapper
public interface ItemMapper {

    void save(Item item);

    // 파라미터가 2개 이상이면 @Param("name")으로 매핑
    void update(@Param("id") Long id, @Param("updateParam") ItemUpdateDto
updateParam);

    Optional<Item> findById(Long id);

    List<Item> findAll(ItemSearchCond itemSearch);
}

 

XML

XML 파일 경로는 resources 하위에 mapper 와 같은 패키지 위치로 맞추어 생성한다. 

<insert id="save" useGeneratedKeys="true" keyProperty="id">
    insert into item (item_name, price, quantity)
    values (#{itemName}, #{price}, #{quantity})
</insert>
  • id는 인터페이스에 설정한 메서드 명이랑 맞추고 파라미터는 #{} 문법을 사용하면 된다.
  • 파라미터가 2개 이상일 경우는 Mapper 인터페이스에 @Param으로 이름을 지정해서 파라미터를 구분해야 한다.
  • resultType은 반환 타입으로 결과를 해당 타입의 객체에 매핑해준다.
  • 반환 객체가 여러개면 컬렉션을 사용하면 되는데 주로 List를 사용한다.

 

<select id="findAll" resultType="Item">
    select id, item_name, price, quantity
    from item
    <where>
        <if test="itemName != null and itemName != ''">
            and item_name like concat('%',#{itemName},'%')
        </if>
        <if test="maxPrice != null">
            and price &lt;= #{maxPrice}
        </if>
    </where>
</select>
  • 동적 쿼리 문법인 <where>은 내부 동적 쿼리가 생성이 되면 맨 앞에 and를 where로 변환하고 생성이 되지 않을 경우는 where를 만들지 않는다.
  • XML에는 HTML 엔티티를 사용할 수 없는데 CDATA 문법을 사용하면 태그를 단순 문자로 인식하도록 하지만 <if>, <where>같은 동적 쿼리 문법도 적용되지 않기 때문에 잘 써야 한다.  (<![CDATA[ ... ]]>)

 

동적 SQL

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

 

문자열 치환

#{} 문법은 ?를 넣고 파라미터를 바인딩하는 PreparedStatement 를 사용하는데 파라미터 바인딩이 아닌 문자 그대로를 처리하는 경우 ${} 를 사용하면 되는데 SQL Injection 공격을 당할 수 있기 때문에 사용하지 않는 것이 좋다.

 

SQL Fragment

<sql>는 fragment 기능으로 사용할 수 있는데 <include>를 통해 반복 코드를 편리하게 불러올 수 있다.

 

resultMap, 별칭(alias)

컬럼명과 객체의 프로퍼티 명이 다를 경우 별칭 "as"를 사용하거나 resultMap으로 선언해서 사용하면 된다.

 

 

 

* 문법은 필요할 때 찾아서 직접 사용해보는 것이 좋다.

 

 

 

[참고] 인프런 김영한님 강의를 공부한 내용입니다.

+ Recent posts