MyBatis

조승빈·2024년 11월 14일

Spring DB

목록 보기
3/8

Mybatis

MyBatisJdbcTemplate보다 더 많은 기능을 제공하는 SQL 매퍼로, 동적 쿼리를 보다 편리하게 작성할 수 있는 장점이 있다. 쿼리를 XML 파일로 작성하기 때문에 코드가 길어지더라도 가독성이 좋고, 문자열을 더하는 등의 작업이 불필요하다.

JdbcTemplate과 MyBatis의 코드 비교

JdbcTemplate

public List<Item> findByCategory(String category) {
    String sql = "SELECT * FROM items WHERE category = ?";
    return jdbcTemplate.query(sql, new Object[]{category}, new BeanPropertyRowMapper<>(Item.class));
}

MyBatis

<!-- src/main/resources/mappers/ItemMapper.xml -->
<select id="findByCategory" resultType="Item">
    SELECT * FROM items WHERE category = #{category}
</select>
public interface ItemMapper {
    List<Item> findByCategory(@Param("category") String category);
}

MyBatis에서는 XML 파일에서 SQL을 작성하고, #{category}와 같이 파라미터 바인딩을 제공하여 깔끔하게 작성할 수 있다.

MyBatis 적용 방법

1. 의존성 추가

// build.gradle 예시
dependencies {
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.4'
}

2. 설정 파일 작성
application.yml 또는 application.propertiesMyBatis 설정을 추가한다.

mybatis:
  type-aliases-package: hello.itemservice.domain
  configuration:
    map-underscore-to-camel-case: true
  • type-aliases-package: 특정 패키지의 클래스에 대해 별칭을 적용하여 XML에서 사용할 수 있게 한다.
  • map-underscore-to-camel-case: 데이터베이스 필드의 스네이크 케이스를 Camel Case로 자동 매핑해준다.

3. 인터페이스와 XML 파일 작성
인터페이스 파일을 생성하고, @Mapper 어노테이션으로 XML 파일과 연동한다.

예를 들어 ItemMapper 인터페이스와 매칭되는 ItemMapper.xml을 생성하여 사용한다.

@Mapper
public interface ItemMapper {
    Item findById(@Param("id") Long id);
    List<Item> findAll();
}
<!-- src/main/resources/mappers/ItemMapper.xml -->
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="hello.itemservice.repository.ItemMapper">
    <select id="findById" parameterType="long" resultType="Item">
        SELECT * FROM items WHERE id = #{id}
    </select>

    <select id="findAll" resultType="Item">
        SELECT * FROM items
    </select>
</mapper>

XML 파일 작성 시 주의사항

XML 파일에서 <, >와 같은 특수문자를 직접 사용할 수 없기 때문에, &lt;, &gt; 와 같이 대체 문자를 사용해야 한다.
XML 문서의 루트 엘리먼트로 <mapper>를 선언하고, namespace에 해당 매퍼 인터페이스의 패키지 경로를 설정해 MyBatis가 이를 참조할 수 있도록 한다.

동적 SQL 작성 예시

MyBatis<if>, <choose>, <where> 등의 태그를 제공하여 동적으로 SQL을 구성할 수 있다.

<select id="findItems" resultType="Item">
    SELECT * FROM items
    <where>
        <if test="category != null">
            AND category = #{category}
        </if>
        <if test="price != null">
            AND price &lt;= #{price}
        </if>
    </where>
</select>

이러한 기능을 통해 조건에 따라 쿼리의 일부를 동적으로 추가할 수 있으며, 반복적인 쿼리 작성을 줄일 수 있다.

자세한 문법은 공식 사이트를 참고하자

Mapper 프록시(Proxy) 메커니즘

@Mapper 어노테이션이 붙은 인터페이스가 구현체 없이 빈으로 등록되고 실행되는 이유는 MyBatisMapper 프록시(Proxy) 메커니즘 덕분이다.

  1. 프록시 객체 생성
    Spring Boot가 애플리케이션을 실행할 때 @Mapper 어노테이션이 붙은 인터페이스를 검색하고, 이를 바탕으로 MyBatis가 내부적으로 프록시 객체를 생성한다.

  2. MyBatis-Spring 통합 동작
    MyBatisSpringMapperScannerConfigurer 또는 @MapperScan을 통해 @Mapper 인터페이스를 찾아 빈으로 등록한다.

구현체 없이도 동작하는 이유

  • Spring의 AOP 기반 프록시 생성
    SpringJavaProxy 클래스를 사용해 런타임에 동적으로 객체를 생성한다.
    @Mapper 인터페이스를 기반으로 동적 프록시를 생성해, 메서드 호출을 MyBatis 실행 로직으로 위임한다.

  • MyBatis의 SQL 매퍼 연결
    MyBatisXML 매퍼어노테이션 기반 SQL을 통해 실제 데이터베이스와 상호작용한다.
    프록시는 이를 호출하기만 하므로 구현체가 없어도 동작한다.

profile
평범

0개의 댓글