시냅스

Spring MyBatis 정리 본문

Java, Spring

Spring MyBatis 정리

ted k 2022. 9. 3. 15:23

MyBatis

  • JdbcTemplate 보다 더 많은 기능을 제공하는 SQL Mapper이다.
  • SQL을 XML에 편리하게 작성할 수 있다.
  • 동적 쿼리에 대한 보완이 크게 이뤄졌다.
  • 추가적인 설정이 필요하다.

 

용례 - Mapper

@Mapper
public interface Mapper {
    void save(Item item);

    void update(@Param("id") Long id, @Param("updateParam") ItemUpdateDto updateParam);

    Optional<Item> findById(Long id);

    List<Item> findAll(ItemSearchCond itemSearch);
}

 

  • MyBatis 매핑 XML을 호출해주는 인터페이스이다.
  • @Mapper 를 통해 mapper라는 것을 선언한다.
  • 이 인터페이스의 메서드를 호출하면 xml의 해당 sql을 실행하고 결과를 돌려준다.
  • xml은 src/main/resources 하부에 패키지 위치를 맞춰 작성해야 한다.

 

용례 - insert

<insert id="save" useGeneratedKeys="true" keyProperty="id">
    insert into item (item_name, price, quantity)
    values (#{itemName}, #{price}, #{quantity})
</insert>
  • insert 태그로 바인딩한다.
  • id는 매퍼 인터페이스에 설정한 메서드의 이름을 지정한다.
  • useGeneratedKey를 통해 DB가 생성해주는 키라는 것을 명시하고, 그 key는 keyProperty에서 id로 설정한다
  • #{} 을 통해 데이터를 바인딩한다.

 

용례 - update

    <update id="update">
        update item
        set item_name=#{updateParam.itemName},
            price=#{updateParam.price},
            quantity=#{updateParam.quantity}
        where id = #{id}
    </update>
  • ${}에 데이터를 바인딩할 때, 매퍼 인터페이스에서 지정한 @Param을 사용한다.
  • 만약 파라미터가 1개만 있었다면, @Param을 사용하지 않아도 된다.

 

용례 - 단건 조회

    <select id="findById" resultType="Item">
        select id, item_name, price, quantity
        from item
        where id=#{id}
    </select>
  • resultType에 맵핑되어 있는 Item은 객체이다.
    • 이 객체의 경로를 application.properties에서 지정하여 앞의 모든 경로를 생략할 수 있었다.
  • 결과는 객체로 나오는데, 이 때 item_name은 camel case로 변환된다. 
    • mybatis.configuration.map-underscore-to-camel-case=true 를 application.properties에서 지정한 덕분인다

 

용례 - 다건 조회

    <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에서 if 문을 통해 동적 쿼리를 시행한다.
  • 만약 if가 하나라도 성공하면 처음 나타나는 and를 where로 변환한다
     
  • 괄호의 경우 HTML entity를 사용한다.

 

용례 - 실제 Java class 단위에서의 사용

@Repository
@RequiredArgsConstructor
public class MyBatisItemRepository {

    private final ItemMapper itemMapper;

    @Override
    public Item save(Item item) {
        log.info("itemMapper class = {}", itemMapper.getClass());
        itemMapper.save(item);
        return item;
    }

    @Override
    public void update(Long itemId, ItemUpdateDto updateParam) {
        itemMapper.update(itemId, updateParam);
    }

    @Override
    public Optional<Item> findById(Long id) {
        return itemMapper.findById(id);
    }

    @Override
    public List<Item> findAll(ItemSearchCond cond) {
        return itemMapper.findAll(cond);
    }
}
  • 이후 repository에서는 ItemMapper를 DI 받아 인터페이스에서 선언한 함수들을 사용할 수 있다.

 

설정 원리

  • 애플리케이션 로딩 시점에 MyBatis 스프링 연동 모듈은 @Mapper가 붙어있는 인터페이스를 조사한다.
  • 해당 인터페이스가 발견되면 동적 프록시 기술을 사용해서 Mapper 인터페이스의 구현체를 만든다.
  • 생성된 구현체를 스프링 빈으로 등록한다.
  • 구현체는 XML의 데이터를 찾아 호출한다.
  • 스프링 예외 추상화도 함께 적용된다.
  • 데이터베이스 커넥션, 트랜잭션과 관련된 기능도 마이바티스와 함께 연동하고 동기화해준다.

 

MyBatis Guide Page

 

Comments