MyBatis 알아보기, Spring Boot 연동 및 환경 설정

Doridam·2023년 6월 8일
0

MyBatis 🕊

목록 보기
1/2

MyBatis

MyBatis는 자바의 영속성 프레임워크로 자바 어플리케이션에서 JDBC를 통한 데이터베이스로의 접근 및 쿼리 수행을 간소화하고 SQL 쿼리와 프로그램 코드를 분리하여 가독성 및 유지보수의 이점을 가지고 있다.

※ 영속성이란 : 데이터를 생성, 사용후에도 지속성을 보장하는것. 데이터의 안정성과 일관성을 보장한다.

특징

  • 객체와 SQL 사이의 여러가지 Mapping 방법을 지원하여 유지보수 및 사용성이 편하다.
  • SQL문과 프로그래밍 코드 분리 가능하다.
  • 다양한 프로그래밍 언어 사용 가능하다.
  • 동적 쿼리와 다양한 파라미터의 바인딩이 가능하다.
  • 커밋, 롤백등 트랜잭션 관리가 가능하다.
  • 다양한 DB 지원
  • 자체적으로 chache를 지원하고 범위 지정 및 온오프를 할 수 있다.

환경설정

※ 프로젝트 환경 : SpringBoot 2.7.12, OracleDB, Window, IntelliJ, Gradle

1. Dependency 추가

1-1 Gradle의 경우 / build.gradle

	implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.3.0'
	runtimeOnly 'com.oracle.database.jdbc:ojdbc8'

1-2 Maven의 경우 / pom.xml

<dependency>
  <groupId>com.oracle.database.jdbc</groupId>
  <artifactId>ojdbc8</artifactId>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>2.3.0</version>
</dependency>

2. application.properties 설정 추가

2-1 DB 설정


DB와의 연결을 위한 url 및 유저 정보를 설정 한다. Oracle을 기준으로 작성된 APITEST 계정의 설정 사항

2-2 mapper 파일에 대한 경로 지정

#mapper에 대한 경로를 resources/mybatis/mappers/ 의 모든 xml파일로 지정한다.
mybatis.mapper-locations=mybatis/mappers/*.xml

2-3 사용할 수 있는 주요 옵션

# MyBatis의 설정 파일(XML)의 경로를 지정한다. 설정한 classpath 하위에 config 파일을 가르킨다.
mybatis.config-location=classpath:mybatis-config.xml 
ㅤ
# 카멜 케이스와 스네이크 케이스의 대한 mapping을 자동 설정한다.
mybatis.configuration.map-underscore-to-camel-case=true
ㅤ
# 선택한 패키지 하위 클래스에 별칭을 정한다. com.apiTest 패키지 하위 클래스를 모두 클래스명으로한
별칭으로 정한다.
mybatis.type-aliases-package=com.apiTest.firstTest
ㅤ
# 캐시 사용 여부 설정
mybatis.configuration.cache-enabled=false

링크에서 설정에 대한 다른 정보 확인 할 수 있다.

3. Mapper.xml 작성

<?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="TestMapper">
    <select id="testSelect" resultType="Test">
        SELECT * FROM TEST
    </select>
  	<update id="testUpdate">
  		UPDATE TEST SET USER_NAME=#{userName} WHERE USER_NO=#{userNo}
  	</update>
   	<insert id="testInsert">
  		INSERT INTO TEST VALUES(#{userNo},#{userName})
  	</insert>
    <delete id="testDelete">
  		DELETE FROM TEST WHERE USER_NO = #{userNo}
  	</delete>
</mapper>

DB를 바탕으로 Mapper.xml을 작성한다. 보기와 같이 SELECT, UPDATE, INSERT, DELETE를 쿼리로 작성하여 수행한다.

<mapper namespace="mapper에서 사용될 이름">

먼저 mapper로 사용될 이름을 지정한다.

    <select id="testSelect" resultType="Test">
        SELECT * FROM TEST
    </select>
  	<update id="testUpdate">
  		UPDATE TEST SET USER_NAME=#{userName} WHERE USER_NO=#{userNo}
  	</update>
   	<insert id="testInsert">
  		INSERT INTO TEST VALUES(#{userNo},#{userName})
  	</insert>
    <delete id="testDelete">
  		DELETE FROM TEST WHERE USER_NO = #{userNo}
  	</delete>

mapper 태그 내부에 사용할 쿼리에 대한 엘리먼트를 작성하고 그에 맞는 쿼리를 작성한다.
SELECT 같은 경우 resultType 또는 resultMap과 같은 결과값 타입을 지정해야 한다.
이때 WHERE절에 사용될 파라미터에 #{변수명}을 사용하여 동적 바인딩으로 쿼리를 수행 할 수 있다.

4. 테스트

4-1 DB 테스트 테이블 생성 및 테스트 값 세팅

CREATE TABLE TEST(
USER_NO NUMBER PRIMARY KEY,
USER_NAME VARCHAR2(10) NOT NULL
);
INSERT INTO TEST VALUES(1,'A');
INSERT INTO TEST VALUES(2,'B');
INSERT INTO TEST VALUES(3,'C');
INSERT INTO TEST VALUES(4,'D');
INSERT INTO TEST VALUES(5,'E');
COMMIT;

4-2 환경 설정

mapper.xml에 대한 경로를 지정한다.
프로퍼티의 카멜 케이스와 쿼리의 스네이크 케이스를 자동으로 mapping 한다.
com.apiTest 패키지의 하위 클래스들을 클래스명으로 별칭한다.

4-3 테스트 작성

Controller class

@Controller
public class TestController {
    private final TestService testService;public TestController(TestService testService) {
        this.testService = testService;
    }@GetMapping("/selectTest")
    public void test(){
        List<Test> tests = testService.mybatisTest();
        for(Test test : tests){
            System.out.println(test.toString());
        }
    }
}

Service interface 및 class

public interface TestService {
    List<Test> mybatisTest();
}
-----------------------------------------------------------------
@Service
public class TestServiceLogic implements TestService{
    private final TestRepository testRepository;public TestServiceLogic(TestRepository testRepository) {
        this.testRepository = testRepository;
    }@Override
    public List<Test> mybatisTest() {
        return testRepository.mybatisTest();
    }
}

Repository interface 및 class

public interface TestRepository {
    List<Test> mybatisTest();
}
-----------------------------------------------------------------
@Repository
public class TestRepositoryLogic implements TestRepository{
    private final SqlSession session;public TestRepositoryLogic(SqlSession session) {
        this.session = session;
    }@Override
    public List<Test> mybatisTest() {
        return session.selectList("TestMapper.testSelect");
    }
}

DTO

public class Test {
    private int userNo;
    private String userName;
    ...getter, setter
}


해당 코드는 Controller에서 Get 요청으로 "/selectTest"를 받게 되면 testService의 mybatisTest()를 거쳐 testRepository의 session.selectList("TestMapper.testSelect")를 실행하게 된다.

sesson : sql 사용을 위한 선언
selectList() : select를 수행, 쿼리 수행 후 결과값이 여러개, 리턴값은 List<obj>이다.
"TestMapper.testSelect" : Mapper의 nameSpace 지정.해당 Mapper 내부 엘리먼트를 지정한다.

작업이 실행된 후 결과는 콘솔에 System.out.println(test.toString()) 를 통해 테스트 통과를 확인할 수 있다.


Mapping에 대한 여러가지 방법

기본 Mapping

프로퍼티(카멜 케이스)와 컬럼명(스네이크 케이스)으로 Mapping 하는 방법

프로퍼티(카멜 케이스) 테이블(스네이크 케이스)결과
mybatis.configuration.map-underscore-to-camel-case=true
--------------------------------------------------------
<select id="testSelect" resultType="Test">
   SELECT * FROM TEST
</select>

application.properties에 위 설정을 추가후 아래 쿼리를 실행한 결과 자동으로 프로퍼티와 컬럼이 Mapping되어 결과값이 정상적으로 출력되는 모습을 확인 할 수 있다.

※ 카멜 케이스 : camelCase. 첫번째 단어는 소문자로 시작하고, 두번째 단어는 대문자로 시작한다.
※ 스네이크 케이스 : snake_case. 첫번째 단어와 두번째 단어 사이에 언더바를 사용한다.

ResultMap

XML파일에 resultMap 요소를 적용하여 컬럼명과 프로퍼티의 이름이 다른경우에도 Mapping이 가능하다.

프로퍼티 테이블결과
<resultMap id="testMap" type="Test">
    <id column="no" property="userNo" jdbcType="INTEGER" javaType="int"/>
    <result column="name" property="userName" jdbcType="VARCHAR" javaType="String"/>
</resultMap>
<select id="test" resultMap="testMap">
   SELECT * FROM API_TABLE
</select>

자바 프로퍼티명과 Table의 컬럼명이 다름에도 resultMap을 사용하여 결과값이 자동으로 Mapping된 것을 확인 할 수 있다.

id는 테이블의 pk값을 의미하며 result는 컬럼을 의미한다.
column : 컬럼명
property : 프로퍼티명
jdbcType,javaType : java와 sql의 데이터 타입이 다르기 때문에 설정을 통해 mapping 해준다.

※ jdbc, javaType 에 대한 mapping 목록 : 링크


Cache에 관하여

MyBatis는 자체적으로 cache를 지원한다. cache에 조회된 결과를 임시로 저장하고 동일한 요청이 있을시 다시 DB에서 조회하는것이 아닌 저장된 결과값을 재사용 함으로써 DB성능 향상에 큰 도움을 줄 수 있다.

  • 만약 cache의 데이터와 DB의 데이터가 불일치할 경우
    - Insert, Update, Delete와 같은 작업이 있을 경우 저장된 cache와 DB가 불일치 할 수 있다. 이런 경우를 위해 해당 작업이 수행될 경우 자동으로 cache를 비우거나 일정시간 간격으로 비우게 된다.
    ※ MyBatis에서 cache는 Mapper 단위로 생성되기 때문에 Table 별로 Mapper를 생성하는것이 바람직 하다.
  • 조회결과는 최대 1024개까지 저장된다.
  • cache가 꽉찰경우 오래된 순으로 먼저 지워진다.
profile
도리도리담담 🐤🐥🐤🐥🐣🐣

0개의 댓글