kimjingyu 2023. 3. 5. 18:13
728x90
  • 장점
    • SQL을 XML에 편리하게 작성할 수 있고, 동적 쿼리를 매우 편리하게 작성할 수 있다.
  • 단점
    • JdbcTemplate 은 스프링에 내장된 기능이고, 별도의 설정없이 사용할 수 있다.
    • MyBatis는 약간의 설정이 필요한다.

설정

mybatis-spring-boot-starter 라이브러리를 사용하면 MyBatis를 스프링과 통합하고, 설정도 아주 간단히 할 수 있다.

//MyBatis 추가
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
  • 스프링 부트가 버전을 관리해주는 공식 라이브러리가 아니기 때문에 버전 정보를 붙여야 한다.
  • 라이브러리
    • mybatis-spring-boot-starter : MyBatis 를 스프링 부트에서 편리하게 사용할 수 있게 시작하는 라이브러리
    • mybatis-spring-boot-autoconfigure : MyBatis와 스프링 부트 설정 라이브러리
    • mybatis-spring : MyBatis와 스프링을 연동하는 라이브러리
    • mybatis : MyBatis 라이브러리
  • application.properties
#MyBatis
mybatis.type-aliases-package=hello.itemservice.domain
mybatis.configuration.map-underscore-to-camel-case=true
logging.level.hello.itemservice.repository.mybatis=trace
  • MyBatis에서 타입 정보를 사용할 때는 패키지 이름을 사용해야 한다. 이때, mybatis.type-aliases-package 에 명시하면 패키지 이름을 생략할 수 있다. ( 여러 위치 지정시 , ; 로 구분 )
  • JdbcTemplate의 BeanPropertyRowMapper 에서 처럼 언더바를 카멜로 자동 변경해주는 기능을 활성화하려면, mybatis.configuration.map-underscore-to-came-case 를 설정한다.
  • MyBatis에서 실행되는 쿼리 로그를 확인하려면 logging.level.hello.itemservice.repository.mybatis 를 설정한다.

적용

XML에 작성한다는 점을 제외하고, JDBC 반복을 줄여준다는 점에서 기존 JdbcTemplate과 거의 유사하다.


마이바티스 매핑 XML을 호출해주는 Mapper Interface

  •  @Mapper
    • MyBatis에서 인식할 수 있게해줌
  • Interface의 메서드 호출시 xml의 해당 SQL을 실행하고 결과를 돌려준다.

ItemMapper.xml

  • namespace : 앞서 만든 Mapper Interface를 지정하면 된다.

  • insert- save
void save(Item item);
<insert id="save" useGeneratedKeys="true" keyProperty="id">
    insert into item (item_name, price, quantity) values (#{itemName}, #{price}, #{quantity})
</insert>
  • Insert SQL
    • id에는 Mapper Interface에 설정한 메서드 이름 지정
    • 파라미터는 #{} 문법 사용.
      • Mapper에서 넘긴 객체의 Property 이름을 적어주기
      • PreparedStatement 를 사용한다.
      • JDBC의 ?를 치환한다고 생각하면 된다.
    • useGeneratedKeys는 데이터베이스가 키를 생성해주는 IDENTITY 전략일때 사용
    • keyProperty는 생성되는 키의 속성 이름을 지정

  • update - update
void update(@Param("id") Long id, @Param("updateParam") ItemUpdateDto updateParam);
<update id="update">
    update item set item_name=#{updateParam.itemName}, price=#{updateParam.price}, quantity=#{updateParam.quantity} where id = #{id}
</update>
  • Update SQL은 <update>를 사용하면 된다.
  • 파라미터가 2개 이상이면 @Param으로 이름을 지정해서 파라미터를 구분해야 한다.

  • select - findById
Optional<Item> findById(Long id);
<select id="findByID" resultType="Item">
    select * from item where id = #{id}
</select>
  • Select SQL은 <select>를 사용하면 된다.
  • resultType은 반환 타입을 명시한다.
    • 여기서는 결과를 Item 객체에 매핑한다.
    • application.properties 에서 mybatis.type-aliases-package=hello.itemservice.domain 속성을 지정해서 모든 패키지 명을 다 적지 않아도 된다.
    • JdbcTemplate의 BeanPropertyRowMapper 처럼 SELECT SQL의 결과를 편리하게 객체로 바로 변환해준다.
  • 자바 코드에서 반환 객체가 하나이면 Item, Optional<Item>과 사용
  • 반환 객체가 하나 이상이면 컬렉션을 사용

  • select - findAll
List<Item> findAll(ItemSearchCond itemSearch);
<select id="findAll" resultType="Item">
    select * 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>
  • Mybatis는 <where>, <if> 같은 동적 쿼리 문법을 통해 편리한 동적 쿼리를 지원한다.
    • <if> 는 해당 조건이 만족하면 구문을 추가
    • <where> 는 적절하게 where 문장을 만들어준다.
      • <if> 모두 실패시 where 절을 만들지 않음
      • <if> 하나라도 성공하면 처음 나타나는 and를 where로 변환
  • XML 특수문자
    • < : &lt;
    • > : &gt;
    • & : &amp;
  • XML CDATA 구문 문법
    • 이 안에서는 특수문자 사용가능
    • XML TAG 가 단순 문자로 인식되어 <if>, <where> 가 적용되지 않음
<if test="maxPrice != null">
    <![CDATA[
    and price <= #{maxPrice}                
    ]]>
</if>

분석

ItemMapper Interface 의 구현체가 없는데 동작하는 이유 -> MyBatis 스프링 연동 모듈에서 자동 처리

MyBatis 설정 원리

MyBatis 스프링 연동 모듈이 자동으로 등록해주는 부분은 MybatisAutoConfiguration 클래스를 참고한다.


기능 정리

동적 SQL

  • if
    • 해당 조건에 따라 값을 추가할지 말지 판단한다.
    • 내부 문법은 OGNL을 사용한다.
<select id="findActiveBlogWithTitleLike" resultType="Blog">
    SELECT * FROM BLOG WHERE state = ‘ACTIVE’
    <if test="title != null">
      AND title like #{title}
    </if>
</select>
  • choose, when, otherwise
    • 자바의 switch 구문과 유사한 구문
<select id="findActiveBlogLike" resultType="Blog">
    SELECT * FROM BLOG WHERE state = ‘ACTIVE’
    <choose>
      <when test="title != null">
        AND title like #{title}
      </when>
      <when test="author != null and author.name != null">
        AND author_name like #{author.name}
      </when>
      <otherwise>
        AND featured = 1
      </otherwise>
    </choose>
</select>
  • trim, where, set
    • <where>는 문장이 없으면 where를 추가하지 않는다.
    • 문장이 있으면 where를 추가한다.
    • 만약 and 가 먼저 시작된다면 and를 지운다.
    • trim이라는 기능을 사용해도 where와 같은 기능을 수행한다.
<select id="findActiveBlogLike"
       resultType="Blog">
    SELECT * FROM BLOG
    <where>
      <if test="state != null">
           state = #{state}
      </if>
      <if test="title != null">
          AND title like #{title}
      </if>
      <if test="author != null and author.name != null">
          AND author_name like #{author.name}
      </if>
    </where>
</select>
<trim prefix="WHERE" prefixOverrides="AND |OR ">
    ...
</trim>
  • foreach
    • 컬렉션 반복 처리시 사용
    • where in (1,2,3,4,5,6) 과 같은 문장을 쉽게 완성
    • 파라미터로 List를 전달한다.
<select id="selectPostIn" resultType="domain.blog.Post">
    SELECT *
    FROM POST P
    <where>
      <foreach item="item" index="index" collection="list"
          open="ID in (" separator="," close=")" nullable="true">
            #{item}
      </foreach>
	</where>
</select>
728x90