본문 바로가기
Spring

Spring Boot + gradle + Oracle 11g + MyBatis 연동

by 매트(Mat) 2021. 5. 31.

Spring Boot + gradle + Oracle 11g + MyBatis 연동

  • 먼저 SQL Developer 또는 CMD(sqlplus -> 환경변수 설정)로 System 계정으로 들어가 유저를 생성합니다.
  • 모든 권한 부여도 해주고,
  • 기본적으로 DB 포트번호가 8080으로 되어있을텐데 9090으로 변경해줍니다.
//유저 생성
create user my_book IDENTIFIED BY my_book
default tablespace users
temporary tablespace temp;

//권한 부여
grant connect, dba to my_book;

//포트 번호 확인
select dbms_xdb.gethttpport() from dual; //8080

//포트 번호 변경
exec dbms_xdb.sethttpport(9090);


커넥션 풀 설정

  • 매번 DB Connection을 선언하는 코딩 방식은 좋지 않습니다. (반복되는 코드, 유지보수 이유 등등)
  • 따라서 커넥션 풀을 설정하여 미리 연결을 통해 맺은 객체들을 pool(풀)에 저장해두었다가 요청이 들어오면 connection을 해주고, 처리가 다 끝나면 다시 반납해줘서 pool에 저장하는 방식을 말합니다.
  • 설정하는 방법은 DataSource 설정하는 것인데 스프링부트를 사용하면 application.properties에서 설정이 가능합니다.
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/xe
spring.datasource.username=my_book
spring.datasource.password=my_book
#이러면 일단 오라클 연동은 끝이납니다. (스프링부트의 장점)


MyBatis 설정

전통적인 JDBC 프로그램 MyBatis
직접 Connecdtion을 맺고 마지막에 close() 자동으로 Connection close() 기능
PreparedStatement 직접 생성 및 처리 MyBatis 내부적으로 PreparedStatement 처리
PreparedStatement의 setXXX() 등에 대한 모든 작업을 개발자가 처리 #{prop}와 같이 속성을 지정하면 내부적으로 자동처리
select의 경우 직접 ResultSet 처리 리턴 타입을 지정하는 경우 자동으로 객체 생성 및 ResultSet 처리
  • 기존의 SQL을 그대로 활용할 수 있고, JDBC의 대안으로 많이 쓰입니다. (현재는 JPA가 대세)
  • MyBatis를 사용하려면 의존성을 추가해야합니다. 스프링부트의 경우 mybatis-starter 하나만 추가해주면 관련된 모든 라이브러리들이 같이 추가됩니다.
  • build.gradle에 추가
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.4'


1. @MapperScan

  • MyBatis의 가장 핵심적인 객체는 SQLSessionSQLSessionFactory 객체입니다.
  • SQLSessionFactory는 내부적으로 SQLSession을 생성해내는데 이 SQLSession을 통해서 Connection을 생성하거나 원하는 SQL을 전달하고, 결과를 리턴받는 구조로 작성하게 됩니다.
  • 스프링은 SQLSessionSQLSessionFactory 객체를 생성하여 빈으로 등록해야 하지만 스프링부트에서는 메인 애플리케이션에 @MapperScan을 사용하면 스프링 부트가 @Mapper가 붙은 MyBatis 매퍼를 스캔하여 빈으로 등록할 수 있도록 합니다.
  • 스프링 부트 메인 애플리케이션 클래스 @MapperScan을 붙이고 mapper 패키지 경로를 입력합니다.


2. application.properties

# MyBatis
# mapper.xml 위치 지정
mybatis.mapper-locations: mybatis-mapper/**/*.xml

# model 프로퍼티 camel case 설정
mybatis.configuration.map-underscore-to-camel-case=true

# 패키지 명을 생략할 수 있도록 alias 설정
mybatis.type-aliases-package=com.azurealstn.codespringweb.domain

# mapper 로그레벨 설정
logging.level.com.azurealstn.codespringweb.mapper=TRACE


3. Mapper(인터페이스, XML) 생성

  • Mapper를 작성하는 방법이 두 가지가 있습니다. 하나는 애노테이션, 다른 하나는 XML을 이용하는 방법이 있습니다. 두 방법 모두 장단점이 있으니 일단 모두 구현해보겠습니다.

애노테이션 구현 방법

tempsnip
  • 먼저 mapper 디렉토리를 만들어 TimeMapper 인터페이스를 생성합니다.
  • 여기서 중요한 점은 TimeMapper 인터페이스에 이 인터페이스가 Mapper라는 것을 인식할 수 있게 @Mapper을 꼭 붙여주어야 합니다. 그래야 @MapperScan에서 찾을 수 있습니다.
  • 만약 스프링 부트가 아닌 스프링을 사용하신다면 root-context.xml 파일에 설정을 해주어야 합니다.

TimeMapper 인터페이스

package com.azurealstn.codespringweb.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface TimeMapper {

    @Select("select sysdate from dual")
    public String getTime();
}

Test 하기

캡처
  • test 폴더안에 TimeMapperTest 클래스를 만들고 코드를 작성합니다.
  • 초록색 체크 표시가 뜨면 정상 동작 확인
package com.azurealstn.codespringweb.persistence;

import com.azurealstn.codespringweb.mapper.TimeMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@Slf4j
@SpringBootTest
public class TimeMapperTest {

    @Autowired
    private TimeMapper timeMapper;

    @Test
    public void testGetTime() {
        log.info("timeMapper class name: " + timeMapper.getClass().getName());
        log.info("timeMapper time: " + timeMapper.getTime());
    }
}


XML 구현 방법

  • 이제 XML로 구현하는 방법을 알아보겠습니다.
캡처
  • src/main/resources 폴더 내 mybatis-mapper 디렉토리 생성해주고 그 아래 TimeMapper.xml 파일을 생성해줍니다.
  • 우리가 application.properties에서 설정한 경로입니다.
# mapper.xml 위치 지정
mybatis.mapper-locations: mybatis-mapper/**/*.xml
  • 다음으로 TimeMapper 인터페이스에 한 줄 코드를 추가합니다.
package com.azurealstn.codespringweb.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface TimeMapper {

    @Select("select sysdate from dual")
    public String getTime();
    //XML 방식
    public String getTime2();
}
  • 여기서는 SQL을 작성하지 않는데 바로 TimeMapper.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="com.azurealstn.codespringweb.mapper.TimeMapper">
    <select id="getTime2" resultType="string">
        select sysdate from dual
    </select>
</mapper>
  • <mapper> 태그의 namespace의 속성값을 보면 우리가 작성한 TimeMapper 인터페이스의 경로를 나타냅니다.
  • <select> 태그의 id 속성값은 TimeMapper 인터페이스의 메소드 이름과 동일해야 합니다.
  • resultType 속성값은 메소드의 리턴값입니다.

Test 하기

  • test 폴더에서 TimeMapperTest 클래스에 이어서 작성해줍니다.
@Slf4j
@SpringBootTest
public class TimeMapperTest {

    @Autowired
    private TimeMapper timeMapper;

    @Test
    public void testGetTime() {
        log.info("timeMapper class name: " + timeMapper.getClass().getName());
        log.info("timeMapper time: " + timeMapper.getTime());
    }
    //XML 방식
    @Test
    public void testGetTime2() {
        log.info("getTime2");
        log.info("getTime2: " + timeMapper.getTime2());
    }
}


애노테이션 방식과 XML 방식 장단점

애노테이션 방식 XML 방식
애노테이션으로 작성할 경우 코드가 매우 간결하고 한줄로 끝낼 수 있다. XML은 조금 코드가 복잡하다 길다.
복잡한 쿼리문을 짜야할 때 이 방식은 좋지 않다. 복잡한 쿼리문을 짤 때 더 좋다.


도메인 객체

  • domain(혹은 model 혹은 vo) 객체를 생성하고 그 객체와 DB의 테이블과 매핑을 시켜야 하는데, 그것에 대한 설정이 바로 alias 설정입니다.
# 패키지 명을 생략할 수 있도록 alias 설정
mybatis.type-aliases-package=com.azurealstn.codespringweb.domain
  • 이렇게 설정하면 좋은 점이 TimeMapper.xml 파일에 resultType이 string이 아니라 객체(domain)를 반환해야하면 아래처럼 패키지까지 적어야 합니다.
<mapper namespace="com.azurealstn.codespringweb.mapper.TimeMapper">
    <select id="getTime2" resultType="com.azurealstn.codespringweb.domain.Member">
        select sysdate from dual
    </select>
</mapper>
  • 그래서 패키지명을 생략할 수 있도록 설정한 것입니다.




References

 

'Spring' 카테고리의 다른 글

SOLID (IoC, DI)  (0) 2022.04.17
download of template 'org.springframework.templates.mvc' failed  (12) 2021.12.20
DI, IoC, root-context.xml  (0) 2021.05.31
웹 프로젝트 폴더 구조  (0) 2021.05.21
MVC 아키텍처  (0) 2021.05.21

댓글