[Spring] MyBatis

Jiwoo·2024년 6월 27일
0

Spring

목록 보기
17/19

📌 MyBatis

  • RowMapper가 가지고있는 단점인 반복되는 코드를 줄이고 함께있는 프로그램 코드와 쿼리 코드를 분리하여 관리
  • 반복적인 JDBC 프로그래밍을 단순화
  • SQL 쿼리들을 XML 파일에 작성해 코드와 SQL 분리

특징

  • JDBC로 처리하는 코드의 설정(Connection) 부분을 줄이고 실제 SQL문에 연결함으로서 빠른 개발 가능
  • MyBatis 코드는 map 인터페이스와 SQL 쿼리와 ResultSet 매핑을 위한 xml 및 annotation 사용
  • 다른 방식에 비해 객체 자체보다 쿼리에 집중 가능, 유지보수에 용이

한계

  • SQL 직접 작성 (DB 기능에 종속적)
  • 테이블마다 비슷한 CRUD 반복, DB 타입 및 테이블에 종속적

해결책

영속성 컨텍스트 활용해 쓰기 지연

  • 영속성 : 데이터를 생성한 프로그램이 종료되어도 사라지지 않는 데이터 특성
  • 영속성 갖지 않으면 데이터는 메모리에서만 존재하고 종료시 모두 삭제된다
  • 파일이나 DB에 영구 저장함으로써 데이터에 영속성 부여

동작

SqlSession Factory Builder (1), (2), (3)

  • MyBatis 설정 파일 읽어와서 설정 정보 기반으로 SqlSession Factory 생성하는 빌더 객체

MyBatis Config File (2)

  • 매핑해줄 객체 들어있는 패키지 경로
  • Mapping File 목록 지정해주는 설정 파일

SqlSession Factory (3), (5), (6)

  • 설정에 맞게 SqlSession 생성해 들고있는 객체

SqlSession (6), (7), (9), (10)

  • Mapping File에서 쿼리 조회해서 수행하고 응답 받아올 수 있는 세션 객체

Mapper Interface (8), (9)

  • DB에서 조회하는 객체와 Java 프로그램 객체 간 인터페이스 정의하는 객체
  • 방법 1. Dao 클래스 정의 : SqlSession 직접적으로 사용
    • 쿼리문 실행 전 넣어줄 매개변수와 쿼리 결과값의 변형 정의 가능
    • .xml 파일의 쿼리문 id와 mapper 메소드명 일치시킬 필요 X
    • SqlSession 객체 주입받아야 하고 쿼리문 실행 시 항상 호출
    • 쿼리문 호출 시 sqlsession에 쿼리문 id 매개변수로 넘겨야한다
// UserDao.java
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Component;

import com.thesun4sky.querymapper.domain.User;

@Component
public class UserDao {

  // SqlSession 멤버 변수로 사용하며 쿼리파일 수행 요청
  private final SqlSession sqlSession;

  public UserDao(SqlSession sqlSession) {
    this.sqlSession = sqlSession;
  }

  public User selectUserById(long id) {
    return this.sqlSession.selectOne("selectUserById", id);
  }

}
  • 방법 2. Mapper Interface 정의 : SqlSession 간접적으로 사용
    • 메서드 내부 구현 불필요
    • Sqlsession 객체 주입 불필요
    • .xml 파일의 쿼리문 id와 mapper 메서드명 일치
    • .xml Namespace가 실제 Mapper.java 위치 가르켜야 한다
    • 메소드 내부 정의 불가
// UserMapper.java
@Mapper
public interface UserMapper {

  User selectUserById(@Param("id") Long id);

}

Mapping File (10)

  • SqlSession이 실행하는 쿼리 담긴 파일
  • 정의된 인터페이스에 기반해 수행할 쿼리 담아두고
  • 쿼리 수행결과를 어떤 인터페이스 매핑할지 정의해놓은 파일
<!-- UserMapper.xml -->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.thesun4sky.querymapper.mapper.UserMapper">
    <select id="selectUserById" resultType="User">
        select id, name from users where id = #{id}
    </select>
</mapper>

영속성 4가지 상태

  • 비영속 : Entity 객체 만들어져서 저장되지 않은 상태
  • 영속(managed) : Entity가 영속성 컨텍스트에 저장되어 관리할 수 있는 상태
  • 준영속(detached) : 영속성 컨텍스트에 저장되어 있다가 분리된 상태, 더 이상 관리 X
  • 삭제(removed) : Entity를 영속성 컨텍스트와 DB에서 삭제하겠다고 표시한 상태
Item item = new Item();		// 1
item.setItemNm("테스트 상품");	

EntityManager em = entityManagerFactory.createEntityManager();	// 2
EntityTransaction transaction = em.getTransaction();		// 3
	
transaction.begin();		
em.persist(item);		// 4-1
em.flush(item).     // 4-2 (DB에 SQL 보내기/commit시 자동수행되어 생략 가능함)
transaction.commit();		// 5

em.close();			// 6

1️⃣  영속성 컨텍스트에 담을 상품 엔티티 생성
2️⃣  엔티티 매니저 팩토리로부터 엔티티 매니저를 생성
3️⃣  데이터 변경 시 무결성을 위해 트랜잭션 시작
4️⃣  영속성 컨텍스트에 저장된 상태, 아직 DB에 INSERT SQL 보내기 전
5️⃣  트랜잭션을 DB에 반영, 이 때 실제로 INSERT SQL 커밋 수행
6️⃣  엔티티 매니저와 엔티티 매니저 팩토리 자원을 close() 호출로 반환

0개의 댓글