스프링 DB 2편 - 데이터 접근 활용 기술 강의 | 김영한 - 인프런
김영한 | , 백엔드 개발자라면 반드시 알아야하는스프링 데이터 접근 기술 Part.2 📣 확인해주세요!본 강의는 자바 스프링 완전 정복 시리즈의 7번째 강의입니다. 우아한형제들 최연소 기술이사
www.inflearn.com
Mybatis
JdbcTemplate보다 더 많은 기능을 제공하는 SQL Mapper이다.
기본적으로 JdbcTemplate이 제공하는 대부분의 기능을 제공하면서 동적 쿼리를 훨씬 편하게 작성할 수 있다.
build.gradle
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
application.properties
mybatis.type-aliases-package=hello.itemservice.domain
mybatis.configuration.map-underscore-to-camel-case=true
logging.level.hello.itemservice.repository.mybatis=trace
mybatis.type-aliases-package
마이바티스에서 타입 정보를 사용할 때는 패키지 이름을 적어주어야 하는데, 여기에 명시하면 패키지 이름을 생략할 수 있다.
지정한 패키지와 그 하위 패키지가 자동으로 인식된다.
여러 위치를 지정하려면 , , ; 로 구분하면 된다.
mybatis.configuration.map-underscore-to-camel-case
언더바를 카멜로 자동 변경해주는 기능을 활성화 (item_name -> itemName)
logging.level.hello.itemservice.repository.mybatis=trace
MyBatis에서 실행되는 쿼리 로그를 확인할 수 있다.
참고! 스프링 부트 3.0 이상을 사용한다면 2.2.0 대신에 3.0.3을 사용
JdbcTemplate vs Mybatis
SQL 줄바꿈
JdbcTemplate
// 줄바꿈 시 한 칸 띄워야 하는 것에 주의해야 한다.
// 그렇지 않으면 udpate itemset 이런 식으로 문법 오류가 발생한다.
String sql = "update item " +
"set item_name=:itemName, price=:price, quantity=:quantity " +
"where id=:id";
MyBatis
<update id="update">
update item
set item_name=#{itemName},
price=#{price},
quantity=#{quantity}
where id = #{id}
</update>
동적 쿼리
JdbcTemplate
String sql = "select id, item_name, price, quantity from item";
if (StringUtils.hasText(itemName) || maxPrice != null) {
sql += " where";
}
boolean andFlag = false;
if (StringUtils.hasText(itemName)) {
sql += " item_name like concat('%',:itemName,'%')";
andFlag = true;
}
if (maxPrice != null) {
if (andFlag) {
sql += " and";
}
sql += " price <= :maxPrice";
}
log.info("sql={}", sql);
return template.query(sql, param, itemRowMapper());
MyBatis
<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 클래스
@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 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>
... 생략
</mapper>
namespace : 앞서 만든 Mapper 인터페이스를 지정하면 된다.
기본적으로 Mapper 인터페이스와 XML 파일의 경로는 같아야 한다.ItemMapper.java -> src/main/java/hello/itemservice/repository/mybatis/ItemMapper.javaItemMapper.xml-> src/main/resources/hello/itemservice/repository/mybatis/ItemMapper.xml
XML 파일을 원하는 위치에 두고 싶으면 application.properties 에 다음과 같이 설정하면 된다.mybatis.mapper-locations=classpath:mapper/**/*.xml
이렇게 하면 resources/mapper 를 포함한 그 하위 폴더에 있는 XML을 XML 매핑 파일로 인식한다.
이 경우 파일 이름은 자유롭게 설정해도 된다.
INSERT
<insert id="save" useGeneratedKeys="true" keyProperty="id">
insert into item (item\_name, price, quantity)
values (#{itemName}, #{price}, #{quantity})
</insert>
id에는 매퍼 인터페이스에 설정한 메서드 이름을 지정
void save(Item item);
파라미터는 #{} 문법을 사용하면 된다. 그리고 매퍼에서 넘긴 객체의 프로퍼티 이름을 적어주면 된다.
#{} : PreparedStatement 사용 (= JDBC의 ? 치환)useGeneratedKeys : 데이터베이스가 키를 생성해 주는 IDENTITY 전략일 때 사용
keyProperty : 생성되는 키의 속성 이름을 지정
Insert가 끝나면 item 객체의 id 속성에 생성된 값이 입력된다.
UPDATE
<update id="update">
update item
set item_name=#{updateParam.itemName},
price=#{updateParam.price},
quantity=#{updateParam.quantity}
where id = #{id}
</update>
여기서는 파라미터가 Long id , ItemUpdateDto updateParam으로 2개이다.
void update(@Param("id") Long id, @Param("updateParam") ItemUpdateDto updateParam);
파라미터가 1개만 있으면 @Param 을 지정하지 않아도 되지만, 파라미터가 2개 이상이면 @Param으로 이름을 지정해서 파라미터를 구분해야 한다.
SELECT
<select id="findById" resultType="Item">
select id, item_name, price, quantity
from item
where id = #{id}
</select>
resultType : 반환 타입 명시
mybatis.type-aliases-package=hello.itemservice.domain : 반환 타입의 패키지 명 생략
mybatis.configuration.map-underscore-to-camel-case=true : 언더스코어를 카멜 표기법으로 자동 변환 (item_name itemName )
Optional<Item> findById(Long id);
반환 객체가 하나면 Item 또는 Optional<Item>
하나 이상이면 컬렉션 사용 (ex. 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 <= #{maxPrice}
</if>
</where>
</select>
<if> : 해당 조건이 만족하면 실행
<where>
<if>가 모두 실패 -> where 생성x
<if>가 하나라도 성공 -> if 안에 문장 추가 (첫 문장이 and일 땐 where로 변환)
대소 비교
XML에서는 데이터 영역에 <, > 같은 특수 문자를 사용할 수 없다. (xml 태그에서 사용되기 때문)
< : <
> : >
& : &
또는 CDATA 사용
'강의 > 스프링 DB 2편' 카테고리의 다른 글
| 스프링 트랜잭션 전파 (1) (1) | 2025.04.22 |
|---|---|
| 스프링 JdbcTemplate (0) | 2025.02.20 |