2021-07-28 강의록_MyBatis

MIN.DI·2021년 7월 28일
0

강의록

목록 보기
47/54

MyBatis 도 하나의 독립된 프레임 워크이다.
MyBatis를 SQL Mapper FrameWork 라고 함.

MyBatis 설정파일

파일명 : mybatis-config.xml
파일명은 개발자가 짓기 나름이지만, 통상적으로 위와 같이 만듦.
이 설정파일은, 반드시 classpath(build path)에 이 설정xml 파일이 있어야 함.

핵심객체

  1. SqlSessionFactoryBuilder
    (매개변수 없는 생성자로 간단히 생성할 수 있음)
  2. SqlSessionFactory
    (mybatis-config.xml 설정파일을 공장(factory)의 설계도면임.
    이 설계도면을 Builder에게 매개변수로 넘겨주어야, Builder가 Factory를 만들 수 있음)
  3. SqlSession

위 3개의 객체가 있어야, MyBatis를 통한 SQL 처리가 가능

Resources Helper Class

MyBatis 설정파일에 대한, 입력스트림을 쉽게 얻을 수 있도록 도와주는 정적메소드 제공.
설정파일이 classpath 안에만 있다면,
그 위치를 정확히 알지 못해도 Resources 헬퍼클래스를 통해 입력스트림을 얻을 수 있다.


MyBatis에게 SQL 처리를 하라는 지시는,
1. sql 문자열을 준다고 되는게 아니다.
2. "SQL Mapper" 라고 하는 xml 파일을 이용해서 모든 sql문장을 저장/관리 함. (이용/실행)
3. "SQL Mapper" 는 하나의 xml이 아니라, n개의 xml파일로 구성 가능.

이때,
개발자가 MyBatis에게 수행시킬 sql문장이 들어있는 SQL Mapper가
정확히 어떤것을 사용해야 하는지 알려줘야 하는 문제가 발생.
이 문제 때문에, 아래 2가지를 같이 알려줘야 함

  • 정확히 어떤 SQL Mapper xml 파일인지?
  • xml 파일 안에도 sql문장들이 많이 있는데, 이 중 정확히 어떤 sql문장을 수행시켜야 하는가?

(1)

위 두가지 질문에 대한 답으로, 아래의 정보를 개발자가 제공해야 함.

  • 각 sql mapper xml파일마다 이름을 지정(= namespace)
  • 각 sql 문장마다 이름을 지정 (SQL ID)
<?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="Test1">	<!--****** namespace ******-->

    <select id="getTime" resultType="java.lang.String">		<!--****** SQL id ******-->
        SELECT sysdate FROM dual
    </select>

</mapper>

위 mapper xml 파일은, MyBatis 설정파일 (mybatis-config.xml)에 등록해주어야 함.

  <mappers>
    <mapper resource="Test1Mapper.xml"/>
    <mapper resource="Test2Mapper.xml"/>
    ...

  </mappers>

즉,

  1. src/main/resources/<Mapper인터페이스의 패키지 생성>
  2. 1 폴더 아래에, <Mapper인터페이스명>.xml 파일 생성
  3. 2에서 생성한 xml파일의 namespace속성의 값을
    ..namespace=<Mapper인터페이스의 FQCN>으로 지정
  4. 3에서 결정된 xml파일에, sql id를
    mapper interface의 추상메소드 이름과 동일하게 지정

MyBatis의 sql mapper xml 파일에 등록된 sql 문자의 바인드변수(?) 가
2개 이상일 경우에는, SqlSession.selectXXX() 메소드 호출시에,
전달인자 값으로 아래의 2가지 경우가 가능하다

  • Map객체
  • 자바빈즈 규약을 따르는 자바빈 객체

(2)

MyBatis 는 SQL Mapper XML 파일을 사용하지 않고,
MyBatis가 자체적으로 제공하는 어노테이션을 가지고 SQL처리가 가능하다.
(@Select, @Param)

  • 이 방식으로 SQL처리를 하려면, 우선 " 인터페이스 "가 필요함.
  • 두번째로, MyBatis의 Annotation 을 사용해야 함.

mybatis가 proxy객체(proxy pattern)을 생성해서 구현해줌.

import org.apache.ibatis.annotations.Select;

public interface TimeMapper {
	
	
	@Select("SELECT sysdate FROM dual")		// 2nd. condition
	public abstract String getNow();		// 1st. condition
	
} //end interface

이렇게 인터페이스를 사용할 경우, SQL 문장이 바뀌면 수정해주기가 매우 불편하므로
위 예시처럼 아주 간단한 문장일 경우에만 사용한다!!


(3)

위의 SQL Mapper XML 방식 + Interface 방식의 결합 사용
(MyBatis의 어노테이션은 사용하지 않음)

  • 인터페이스와 추상메소드는 선언
  • 대신, SQL문장 ==> SQL Mapper XML 파일에 저장
  • MapperProxy 객체가 생성되면,
    실제 수행시킬 SQL문장은 SQL Mapper XML파일에 등록된 문장을 수행하여 결과 생성

인터페이스와 SQL Mapper XML 파일과의 결합방식으로 SQL 문장을 처리
(1) 이 인터페이스가 소속된 패키지와 동일한 폴더구조를 resources 폴더에 만들어야 한다
(2) (1) 에서 생성된 마지막 폴더 안에, 이 인터페이스 이름과 동일한 SQL Mapper XML 파일을 생성
(3) (2) 에서 생성한 SQL Mapper XML의 파일의 namespace는 패키지 이름.인터페이스 이름과 동일하게 작성
(4) 수행시킬 SQL ID는, 이 추상메소드의 이름과 같게 작성


(4)


<![CDATA[]]> 태그

<, > 등, 태그로 인식될 수 있는 문자들을, 있는 그대로의 문자로 사용하기 위해
<![CDATA[]]> 태그 내부에 작성한다.

특히 DQL문장의 경우 <, > 로 WHERE조건을 주는 경우가 있으므로
꼭 작성하자!
(mybatis 3.x 이상 버전에서는, " > "는 CDATA태그가 없어도 알아서 인식해주지만,
" < " 기호는 인식을 못한다)


MyBatis위에, SqlSessionFactoryBuilder를 만들고,
그 위에 SqlSessionFactory
추상적인 연결인 session 을 보고 함.
유저가 sql을 수행할때마다, session 을 새로 생성해야 함. (쓰레드마다 새로 생성)
따라서 지역변수로 사용.

Spring에서 사용하려면, mybatis-spring 라이브러리를 통해 연동처리 함.

MyBatis는 영속성 계층 (DAO역할)

Spring기반의 컴포넌트는 비즈니스 계층

스프링에서는 mybatis의 핵심객체를 우리가 직접 생성하는게 아니라,
SQLSessionFactory 객체를 beans container에 bean으로 등록

db connection 은 hiariDataSource가 제공하므로,
sqlSessionFactory는 이 커넥션을 이용해 만들기 위해
bean의 property로 지정 (root-context.xml)

root-context.xml에 <bean> 태그로 등록하면,
자동으로 setter 메소드로 등록됨.


INSERT INTO 테이블(컬럼1, 컬럼2, 컬럼3)
VALUE(#{컬럼1}, #{컬럼2}, #{컬럼3});

어떻게 MyBatis는 우리가 준 객체로부터 위의 바인드변수 값을 추출해내는가?

  1. 만약 우리가 준 객체가 자바빈즈 규약을 따르는 객체라면,
    get{프로퍼티명}() 메소드 호출로 각 바인드 변수의 값을 얻어낸다.
    없으면 오류 발생

  2. 만약 우리가 준 객체가 Map<K, V> 라면,
    get{key이름}() 메소드 호출로 각 바인드변수의 값을 얻어낸다.


영속성 계층은 다른 계층은 신경쓰지 않는다.
DTO는 비즈니스계층에서 쓰인다. 영속성계층 호출할때는 DTO로 VO를 만들어서 집어넣는다.
각 계층은 독립성을 유지해야한다.
입력도 VO로 해야함.


selectKey 태그

profile
내가 보려고 쓰는 블로그

1개의 댓글

comment-user-thumbnail
3일 전

좋은 내용 잘 보고 갑니다!

답글 달기