Search
Duplicate
📒

[Spring DB] xx. 마이바티스 개념과 사용

상태
미진행
수업
Database Study
주제
Mybatis
4 more properties
참고

마이바티스

NOTE
Mybatis는 자바 오브젝트SQL사이의 자동 매핑 기능을 지원하는 ORM(Object reliational Mapping)프레임워크이다.
xml문서를 통해 작성하므로 편리하게 작성한다.
mybatis는 동적쿼리를 작성하기 편리하다.

퍼시스턴트

객체가 생성되면 메모리에 올라간다
객체를 이용해서 다루는 데이터들은 객체가 사라지면 함께 사라진다
이렇게 일회용으로 버려지는 데이터들을 유지하기위해서 어딘가에 저장해야하는데 이렇게하면 나중에 객체가 다시 생성되면 재사용이 가능하다 ( 사라지기 전의 상태로 돌아간다 → 영속성(Persistence)라고 함 )

JDBC | MyBatis 비교

NOTE
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());
Java
복사
JDBC 동적 쿼리작성
<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>
XML
복사
Mybatis 동적 쿼리작성 (가독성부터 좋아보임)

마이바티스 적용

NOTE
Mapping 파일에 기재된 SQL을 호출하기 위한 인터페이스
@Mapper public interface ItemMapper{ void save(Item item) // param이 2개이상이면 명시해줘야 한다. void update(@Param("id") Long id, @Param("updateParam") ItemUpdateDto updateParam) List<Item> findAll(ItemSearchCond ItemSearch); Optional<Item> findById(Long id); }
Java
복사
@Mapper를 통해 xml의 해당 SQL을 실행시킬 수 있다.
@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); } }
Java
복사
mapper를 사용하는 Repository
<?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의 패키지경로! ?> <mapper namespace="hello.itemservice.repository.mybatis.ItemMapper"> <? 저장쿼리(useGeneratedKeys - 자동키 생성) ?> <? #{} 로 파라미터가 넘어간다. ?> <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> <? 검색 쿼리 ?> <? resultType을 통해 결과를 자동반환 ?> <select id="findById" resultType="Item"> select id, item_name, price, quantity from item where id = #{id} </select> <? 전체검색 쿼리, 동적쿼리(where) ?> <? <where>는 적절하게 where을 만들어준다. if가 성공하면 생성, 아니면 생성하지않음 ?> <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>
XML
복사
xml파일 위치는 mapper패키지명과 동일해야한다.

마이바티스 경로, 특수문자

NOTE

XML 파일 경로 수정하기

XML 파일을 원하는 위치에 두고 싶으면 application.properties에 다음과 같이 설정하면 된다.
mybatis.mapper-locations=classpath:mapper/**/*.xml
이렇게 하면 resources/mapper 를 포함한 그 하위 폴더에 있는 XML을 XML 매핑 파일로 인식한다. 이 경우 파일 이름은 자유롭게 설정해도 된다.

XML 특수문자

< : &lit
> : &ㅎㅅ
& : &amp

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>
XML
복사
CDATA 사용하기( 단 해당 구문안에서는 XML태그가 일반 문자로 인식된다.)

마이바티스 분석

NOTE
ItemMapper: 매퍼 인터페이스의 구현체가 없는데 어떻게 동작하는가?
동적 프록시 기술로 구현체를 만들어준다.
매퍼 구현체
마이바티스 스프링 연동 모듈이 만들어주는 ItemMapper 의 구현체 덕분에 인터페이스 만으로 편리하게 XML의 데이터를 찾아서 호출할 수 있다.
원래 마이바티스를 사용하려면 더 번잡한 코드를 거쳐야 하는데, 이런 부분을 인터페이스 하나로 매우 깔끔하고 편리하게 사용할 수 있다.
매퍼 구현체는 예외 변환까지 처리해준다. MyBatis에서 발생한 예외를 스프링 예외 추상화인DataAccessException 에 맞게 변환해서 반환해준다. JdbcTemplate이 제공하는 예외 변환 기능을 여기서도 제공한다고 이해하면 된다.
정리
매퍼 구현체 덕분에 마이바티스를 스프링에 편리하게 통합해서 사용할 수 있다.
매퍼 구현체를 사용하면 스프링 예외 추상화도 함께 적용된다.
마이바티스 스프링 연동 모듈이 많은 부분을 자동으로 설정해주는데, 데이터베이스 커넥션, 트랜잭션과 관련된 기능도 마이바티스와 함께 연동하고, 동기화해준다.

동적쿼리

NOTE
Mapping 파일에 기재된 SQL을 호출하기 위한 인터페이스
<select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> </select>
XML
복사
if - 해당조건에 따라 추가할지 판단
<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>
XML
복사
choose, when, otherwise - java의 switch와 같은 개념
<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>
XML
복사
trim, where, set - 동적조건
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P <where> <? open, close는 반복의 시작과 끝을 정의한다 ?> <? ex) SELECT * FROM POST P WHERE ID in (1, 2, 3) ?> <foreach item="item" index="index" collection="list" open="ID in (" separator="," close=")" nullable="true"> #{item} </foreach> </where> </select>
XML
복사
foreach - 컬렉션 반복처리

기타쿼리

NOTE

애노테이션으로 SQL작성 가능

@Select("select id, item_name, price, quantity from item where id=#{id}") Optional<Item> findById(Long id);
Java
복사

문자열 대체

@Select("select * from user where ${column} = #{value}") User findByColumn(@Param("column") String column, @Param("value") String value);
Java
복사
문자 그대로를 처리? ⇒ SQL Injection이 들어올 수 있으므로 쓰지말자

SQL 조각

<sql id="userColumns"> "${alias}.id.${alias}.username,${alias}.password </sql>
XML
복사
<sql>을 통한 코드 재사용
<select id="selectUsers" resultType="map"> select <include refid="userColumns"><property name="alias" value="t1"/></include>, <include refid="userColumns"><property name="alias" value="t2"/></include> from some_table t1 cross join some_table t2 </select>
XML
복사
<include>를 활용해서 <sql>조각 사용가능

ResultMap(별칭관련)

<resultMap id="userResultMap" type="User"> <id property="id" column="user_id" /> <result property="username" column="user_name"/> <result property="password" column="hashed_password"/> </resultMap> <select id="selectUsers" resultMap="userResultMap"> select user_id, user_name, hashed_password from some_table where id = #{id} </select>
XML
복사
resultMap을 통한 별칭연결