LostCatBox

About-mybatis

Word count: 822Reading time: 5 min
2023/01/21 Share

참조

동작원리참조1

jpavsmybatis

왜?

mybatis는 지금 다니고 있는 회사에서 사용하고있는 스펙이다.

jpa 와 mybatis의 차이를 알아보고, mybatis의 동작원리를 이해해보자

MyBatis vs JPA

MyBatis

장점

  • 접근이 쉽고 코드가 간결하다(sql문과 많이 흡사함)
  • 성능-> 직접 sql문 작성하여 최적화된 쿼리 구현가능
  • 다양한 프로그래밍 언어로 구현이 가능하다.(java, ruby 등등)
  • mybatis는 sql을 별도의 xml파일로 분리해서 관리한다. (유지보수 분리)

단점

  • 테이블이 변경되고 dto가 변경될때마다 매핑에 대한 부분을 다시 수정해야한다.
  • application 과 DB간의 설계부분이 수정이 많은경우 많은 설정을 바꿔야한다.
  • 런타임을 해야 오류확인가능
  • DB에 종속적이다. DB 변경시 mapper 전부 수정해야한다.
  • 많은 것에 대한 정의가 필요하다
    Mapper에서 select id로 사용할 인터페이스 설계, 쿼리에 파라미터로 # 혹은 $로 파라미터 바인딩을 위한 model 정의, resultType/ParameterType으로 전달할 model 정의가 필요하다.

MyBatis

자바에서 데이터베이스 프로그래밍을 할 때 JDBC API를 사용한다.

JDBC를 사용하게 쉽게 만든 Mybatis는 SQL Mapper를 통해 자바의 메서드와 SQL 맵핑을 해준다.

스크린샷 2023-01-31 오후 10.35.27

MyBatis3가 데이터베이스에 액세스하는 흐름은 위와 같다.

애플리케이션 시작시 1 ~ 3 프로세스를 수행하고,

클라이언트의 각 요청에 대해 4 ~ 10 프로세스가 수행됩니다.

애플리케이션 시작 시 SqlSessionFactoryBuilder가 MyBatis 설정 파일을 참고하여 SqlSessionFactory를 생성합니다.
이후 Application단에서 데이터 접근 작업시 SqlSessionFactory는 매 요청마다 SqlSession 객체를 생성합니다.
SqlSession 객체를 통해 DB 작업을 진행하는데, 작업시 수행하는 쿼리는 mapper 파일에 담겨있습니다.

DataSource

JDBC API를 이용하여 데이터베이스 연동을 처리하려면 반드시 데이터베이스로부터 커넥션을 얻어와야 한다.
이를 위해 데이터베이스와의 물리적인 연결을 지원하는 DataSource가 필요합니다.

하위 예시

1
2
3
4
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/flab?serverTimezone=UTC&characterEncoding=UTF-8
spring.datasource.username=baesuyeon
spring.datasource.password=baesuyeon

Spring Boot에서는 Java Config 를 통해 DataSource를 설정할수도 있지만 application.properties 파일 내 spring.datasource.* 패턴으로도 설정이 가능합니다. 위와 같이 실제 접속을 위한 데이터베이스 ip, id, pw만 설정해주면 됩니다.

MySQL, MyBatis 의존성 추가

1
2
3
4
compile "org.springframework.boot:spring-boot-starter-jdbc"
compile group: 'mysql', name: 'mysql-connector-java'
compile group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-autoconfigure', version: '2.1.4'
compile group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter', version: '2.1.4'

Mapper Interface

복잡한 쿼리는 XML을 사용하는것이 좋은 방법이 될 수 있습니다.

1
2
3
4
<?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="com.flab.demo.mapper.ProductMapper">
</mapper>

SQL Mapper.xml 파일은 <mapper>를 루트 엘리먼트로 사용합니다.
namespace는 Mapper Interface 경로와 맵핑합니다.

그리고 <insert> <update> <delete> <select> 엘리먼트를 이용하여 필요한 SQL 구문들을 등록합니다.
이때 id 속성은 필수 속성으로 네임스페이스 내부에서 유일한 아이디를 등록해야 합니다.

XML의 id 값과 Interface 내의 메서드명이 일치하면 자동으로 xml과 메서드를 맵핑되어 id로 등록된 SQL을 실행할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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="com.flab.demo.mapper.ProductMapper">

<resultMap type="com.flab.demo.domain.Product" id="product">
<result property="id" column="id"/>
<result property="productName" column="product_name"/>
<result property="fixedPrice" column="fixed_price"/>
<result property="sellerId" column="seller_id"/>
<result property="salesYn" column="sales_yn"/>
<result property="createDate" column="create_date"/>
</resultMap>

<select id="getById" parameterType="Long" resultMap="product">
SELECT *
FROM PRODUCT
WHERE id = #{id}
</select>
<?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="com.flab.demo.mapper.ProductMapper">

<select id="getById" parameterType="Long" resultType="com.flab.demo.domain.Product">
SELECT *
FROM PRODUCT
WHERE id = #{id}
</select>
</mapper>

SELECT SQL 구문이 실행되면 ResultSet이 리턴되며, ResultSet에 저장된 검색 결과를 어떤 자바 객체에 맵핑해야 할지 지정해야 하는데,
이때 resultType, resultMap 속성을 사용할 수 있습니다.

1
2
3
4
<insert id="create" parameterType="com.flab.demo.domain.Product">
INSERT INTO PRODUCT(product_name, fixed_price, seller_id)
VALUES(#{productName}, #{fixedPrice}, #{sellerId})
</insert>

Mapper 파일에 등록된 SQL 실행 시 SQL 실행에 필요한 데이터를 외부로부터 받아야 할 상황이 있을 수 있습니다. 이때 parameterType 속성을 사용할 수 있습니다. 내부적으로 parameter 값을 가져올 수 있는 getter 메서드를 호출합니다.

1
2
mybatis.mapper-locations=mapper/*.xml
mybatis.type-aliases-package=패키지 경로

마이바티스 세팅을 위해 application.properties 파일을 수정합니다.

mybatis.mapper-locations : xml 파일이 위치한 경로/*.xml
mybatis mapper.xml 파일이 있는 폴더 경로를 설정해줍니다.
보통 classpath 를 통해 경로 설정을 해주는데, spring boot로 프로젝트 생성시 classpath는 resources 폴더 입니다.

mybatis.mapper-locations : 매퍼용 클래스가 위치한 경로
Mapper에서 resultType을 단순히 클래스 명으로만 적기 위해 필요합니다.
미설정시 전체 패키지 경로와 클래스명을 작성해야 합니다.

CATALOG
  1. 1. 참조
  2. 2. 왜?
  3. 3. MyBatis vs JPA
    1. 3.1. MyBatis
  4. 4. MyBatis
  5. 5. DataSource
  6. 6. MySQL, MyBatis 의존성 추가
  7. 7. Mapper Interface