MyBatis는 JdbcTemplate이 제공하는 대부분의 기능을 제공한다.SQL을 XML에 편리하게 작성할 수 있고 동적쿼리 사용이 수월하다는 장점이 있다.
Mapper interface는 마이바티스 매핑 xml을 호출해주며 MyBatis에서 인식할 수 있도록 인터페이스에 @Mapper 애노테이션을 붙여준다.
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Optional;
@Mapper
public interface ItemMapper {
void save(Item item);
//parameter가 하나인 경우에는 Param 어노테이션 생략 가능
void update(@Param("id") Long id, @Param("updateParam")ItemUpdateDto updateParam);
List<Item> findAll(ItemSearchCond itemSearch);
Optional<Item> findById(Long id);
}
Java8부터 지원하는 Optional 클래스
Optional 클래스는 NPE(NullPointerException) 예외를 막아준다. 값이 null인 경우에는 null인 값을 감싸는 Wrapper 클래스다.
Mapper interface를 작성했다면 이번엔 SQL이 있는 XML 매핑 파일을 만들어야 한다. 자바코드가 아니기 때문에 'src/main/resources' 하위에 만들어 주어야 하고 mapper interface 파일의 패키지 경로와 동일하게 만들어주어야 한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="project.item.repository.mybatis.ItemMapper">
</mapper>
namespace에서 mapper interface 경로를 지정해주어야 한다. 설정을 완료했다면 mapper 안에 SQL을 작성하면 된다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="project.item.repository.mybatis.ItemMapper">
<insert id="save" useGeneratedKeys="true" keyProperty="id">
insert into item (item_name,price,quantity)
values(#{itemName},#{price},#{quantity})
</insert>
<update id="update">
update item
set item_name = #{updateParam.itemName},
price = #{updateParam.price},
quantity = #{updateParam.quantity}
where id = #{id}
</update>
<select id="findById" resultType="Item">
select id,item_name,price,quantity
from item
where id = #{id}
</select>
<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>
</mapper>
<insert id="save" useGeneratedKeys="true" keyProperty="id">
insert into item (item_name,price,quantity)
values(#{itemName},#{price},#{quantity})
</insert>
id는 mapper interface에 설정한 메서드 이름으로 지정하면 된다. 데이터베이스가 자동으로 키를 생성해주는 전략일때는 useGeneratedKeys를 사용하며 keyProperty는 생성되는 키의 속성 이름을 지정한다.
<select id="findById" resultType="Item">
select id,item_name,price,quantity
from item
where id = #{id}
</select>
resultType으로 반환타입을 명시해준다. 자바 코드에서 반환 객체가 하나이면 '객체명', Optional을 사용하고 여러개일 경우에는 주로 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, if 같은 동적쿼리 문법을 지원하기 때문에 jdbc보다 상대적으로 편리하게 동적쿼리를 작성할 수 있다. 'if'의 조건이 true이면 그 다음 구문이 실행된다.
<if test="maxPrice != null">
and price $lt;= #{maxPrice}
</if>
가격조건을 만드는 동적쿼리문에서 <= 작거나 같다라는 표현을 $lt;= 이렇게 표현했다. xml에서는 '<' 나 '>', '&' 같은 특수문자를 사용할 수 없기 때문에 CDATA 구문 문법을 사용하면 편리하게 특수문자를 사용할 수 있다.
<where>
<if test="itemName != null and itemName != ''">
and item_name like concat('%',#{itemName},'%')
</if>
<if test="maxPrice != null">
<![CDATA[
and price <= #{maxPrice}
]]>
</if>
</where>