[Spring Database] MyBatis
MyBatis는 JdbcTemplate가 제공하는 대부분의 기능을 제공한다.
SQL을 XML을 통해 관리하고, 동적 쿼리 문제를 쉽게 해결할 수 있다는 장점이 있다.
프로젝트에서 동적 쿼리와 복잡한 쿼리가 많이 사용된다면 MyBatis를 사용하는 편이 합리적이고, 단순한 쿼리가 대부분이면 JdbcTemplate을 사용하는 것도 괜찮다.
#MyBatis
mybatis.type-aliases-package=hello.itemservice.domain
mybatis.configuration.map-underscore-to-camel-case=true
logging.level.hello.itemservice.repository.mybatis=trace
application.properties에 MyBatis 관련 내용을 추가해주자.
패키지 정보로 타입 정보를 사용하고, 표기 관례를 맞춰주는 설정이다.
@Mapper
public interface ItemMapper {
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 애너테이션을 붙여서 MyBatis가 인식 할 수 있도록 하고, 인터페이스의 메서드를 호출하면 xml의 해당 SQL을 실행한다.
인터페이스의 구현체는 @Mapper 애너테이션이 붙어있으면 알아서 만들어진다.
여기서 객체를 하나만 가져올 때는 @Param 애너테이션을 생략해도 되지만, update 메서드처럼 두 개 이상을 가져올 때는 생략할 수 없다.
해당 인터페이스의 디렉토리와 동일한 방식으로 resources에 디렉토리를 생성하고, xml 파일도 생성한다.
xml 파일을 원하는 위치에 두려면 application.properties 파일을 수정해야 한다.
mybatis.mapper-locations=classpath:mapper/**/*.xml
이렇게 설정 해 주면 resources/mapper 하위 폴더의 xml 파일을 인식한다.
<?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="hello.itemservice.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 <= #{maxPrice}
</if>
</where>
</select>
</mapper>
MyBatis는 SQL을 xml 형식으로 관리한다.
namespace에는 아까 만든 인터페이스를 지정해주고 인터페이스의 메서드에 해당하는 SQL을 하나하나 작성하자.
insert SQL은 <insert> 태그를 사용해서 구현한다.
SQL의 파라미터들은 #{} 문법과 ItemMapper 인터페이스에서 넘긴 객체의 프로퍼티 이름을 사용해 처리한다.
(#{} 문법은 내부적으로 PreparedStatement를 사용한다)
#바인딩과 $바인딩이 있는데..
#바인딩 시 SQL Injection 공격을 막을 수 있고 소프트파싱을 사용할 수 있어 성능이 최적화 할 수 있으니 특별한 경우가 아니면 #바인딩을 사용하는 편이 합리적이다.
useGeneratedKeys는 데이터베이스가 키를 생성해야 할 때 사용하고, keyProperty는 생성되는 키의 이름을 지정 할 때 사용한다.
update SQL은 <update> 태그를 사용하고, select SQL은 <select> 태그를 사용해서 구현한다.
resultType으로 반환 타입을 명시할 때 사용하는데, application.properties 파일에 패키지 관련 정보를 추가해 줘서 모든 패키지 명을 다 적지 않아도 된다.
결과 반환 시 RowMapper 처럼 select SQL의 결과를 객체로 바로 변환해준다.
findAll을 구현 할 때는 동적 쿼리를 사용한다.
<if> 태그는 해당 조건이 만족하면 구문을 추가하고, <where> 태그는 SQL 문법에 맞도록 where 문장을 만들어준다.
xml을 작성할 때는 태그와 특수문자를 구분하기 위해 $lt 와 같은 이스케이프 문자를 사용하거나 CDATA 문법을 사용한다.
@Repository
@RequiredArgsConstructor
public class MyBatisItemRepository implements ItemRepository {
private final ItemMapper itemMapper;
@Override
public Item save(Item item) {
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);
}
}
MyBatisItemRepository 는 ItemMapper의 구현체에 기능을 위임한다.
@Mapper 애너테이션으로 구현체를 만드는 과정을 자세히 살펴보자.
애플리케이션이 로딩 될 때 MyBatis 스프링 연동 모듈은 @Mapper 애너테이션이 붙어있는 인터페이스를 조사하고, 동적 프록시 기술을 사용해 ItemMapper 인터페이스의 구현체를 만든다.
(구현체는 스프링 빈으로 등록되고, 예외 변환도 처리해준다)
Mapper 구현체 덕분에 MyBatis를 스프링에 통합해서 사용할 수 있다.
이 외에도 MyBatis를 사용하면 동적 쿼리를 쉽게 설계하거나 애너테이션으로 간단한 SQL을 설계하는 등 여러 가지 편리한 기능을 사용할 수 있다.
'Spring > Spring Database' 카테고리의 다른 글
[Spring Database] JPA 적용 (0) | 2022.09.10 |
---|---|
[Spring Database] JPA (1) | 2022.09.09 |
[Spring Database] 데이터베이스 테스트 (2) | 2022.09.07 |
[Spring Database] JdbcTemplate (0) | 2022.09.06 |
[Spring Database] 데이터베이스 예외 처리 (0) | 2022.09.05 |
댓글
이 글 공유하기
다른 글
-
[Spring Database] JPA 적용
[Spring Database] JPA 적용
2022.09.10 -
[Spring Database] JPA
[Spring Database] JPA
2022.09.09 -
[Spring Database] 데이터베이스 테스트
[Spring Database] 데이터베이스 테스트
2022.09.07 -
[Spring Database] JdbcTemplate
[Spring Database] JdbcTemplate
2022.09.06