본문 바로가기

Dev/Spring

[Spring] Spring Boot 시작하기 (4) - Mybatis, MySQL 연동

 

 

 

포스팅 시리즈

 

 

 

본 포스팅은 Spring Boot 프로젝트에서 MyBatis Framework를 이용한 MySQL 연동 방법에 대한 기록입니다.

내용 중 일부는 이전 포스팅에서 설정했던 정보들을 다수 포함하고 있습니다. 따라서 Spring Boot가 처음이신 분들은 본 포스팅만 봐서는 이해되지 않는 내용들이 산재해 있을 수 있으니 이점 양해 부탁드립니다.

 

 

포스팅을 시작하기에 앞서, MySQL이 어딘가에 설치되어 있어야 합니다.

본 포스팅은 MySQL 데이터 베이스가 로컬에 설치되어 있다고 가정합니다.

 

만약 MySQL이 설치되어 있지 않다면 아래의 링크를 참고해서 MySQL을 설치해 줍니다.

2020/03/12 - [Dev/etc] - Windows 환경에서의 MySql5.1~ 설치

2020/03/12 - [Dev/etc] - Linux 환경에서의 MySql5.1~ 설치와 root 계정 접속 세팅

 

Spring Boot에서의 MyBatis 사용법은 Spring Boot 이전 버전에서 사용하던 방식과 크게 다르지 않습니다.

먼저 사용자 관점에서 어떻게 MyBatis가 DB와 상호 작용하는지 알아보겠습니다.

 

 

본 포스팅은 MVC 디자인 패턴을 기본으로 상정하고 있으므로 이를 기준으로 설명합니다.

먼저, 유저의 요청이 들어왔을 때, Controller에서 모든 요청을 수용합니다.

이때, Controller에서는 때로는 복잡한 작업, 때로는 DB와 통신하는 작업 등 수많은 업무에 대한 요청을 받을 텐데, 그 모든 것을 Controller가 홀로 감당하는 형태로 프로그래밍을 하는 경우는 아마도 거의 없을 겁니다.

 

따라서, 보통은 다른 클래스에서 그 일을 대신하게 해 주는데, 위 표에서 Service 클래스가 하는 일이 그것입니다.

Service에서 다시 Mapper Interface로 요청 보내고 DB에 질의할 쿼리문을 관리하는 Mapper파일에 또 요청을 보냅니다.

Mapper 파일은 DB와 직접적으로 상호작용하며, 그에 대한 결과 반환은 위 과정의 역순으로 이루어집니다.

 

그럼 본격적으로 MySQL과 연동하기 위한 구현 과정을 살펴보겠습니다.

 

1. 데이터베이스 및 테이블 생성

프로젝트에 연결할 데이터베이스와 테이블, 그리고 테스트용 데이터를 작성해 주겠습니다.

mysql에 접속하고 아래의 쿼리문을 통해 필요한 정보를 작성합니다.

 

mysql> create database SPRING_BOOT_DB;
mysql> use SPRING_BOOT_DB;
mysql> create table SALARY(ID int, NAME char(20), email char(30));

mysql> insert into SALARY values(1, "AAA", "AAA@example.com");
mysql> insert into SALARY values(2, "BBB", "BBB@example.com");
mysql> insert into SALARY values(3, "CCC", "CCC@example.com");

mysql> flush privileges;

 

SPRING_BOOT_DB라는 데이터 베이스 안에 SALARY라는 테이블을 생성해주고 테스트용 데이터를 삽입해 주었습니다.

아래의 명령어로 테이블이 제대로 세팅되어있는지 확인합니다.

 

mysql> desc SALARY;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| ID    | int      | YES  |     | NULL    |       |
| NAME  | char(20) | YES  |     | NULL    |       |
| email | char(30) | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> select * from SALARY;
+------+------+-----------------+
| ID   | NAME | email           |
+------+------+-----------------+
|    1 | AAA  | AAA@example.com |
|    2 | BBB  | BBB@example.com |
|    3 | CCC  | CCC@example.com |
+------+------+-----------------+
3 rows in set (0.00 sec)

 

2. 의존성 설정

# build.gradle

//mybatis
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3'
//mysql connector
compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.21'

 

Spring Boot 프로젝트로 돌아와, build.gradle 파일에 위의 의존성을 작성합니다.

본 포스팅을 정주행 하신 분들이라면 mybatis 의존성이 주석 처리되어 있을 텐데, 그럴 경우에는 주석을 해제해 주세요.

build.gradle 파일에 변화가 있을 경우, 반드시 Refresh Gradle Project를 해주어야합니다. 

 

3. 데이터 베이스 연결 정보 작성

application.priperties 파일을 열고 아래와 같이 설정 정보를 작성해 줍니다.

 

# application.priperties


spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.url=jdbc:mysql://localhost:3306/SPRING_BOOT_DB?characterEncoding=UTF-8&serverTimezone=UTC

spring.datasource.username={user name}
spring.datasource.password={user password}

# 매핑할 모델의 패키지 경로 (mybatis 매핑 type을 짧게 쓰기 위한 설정)
mybatis.type-aliases-package=com.example.demo.model

# mapper.xml 위치 명시
mybatis.mapper-locations=classpath:com/example/demo/mybatis/**/*.xml

 

type-aliases-package항목은 MySQL과의 상호작용을 통해 주입할 값이나 반환받을 값의 Model이 존재하는 패키지를 의미합니다.

mapper.xml에서 사용하기 위한 정보로, 이전 포스팅에서 생성했던 SalaryModel을 활용할 것입니다.

SalaryModel.java

모델 클래스가 존재하는 패키지 경로를 type-aliases-package에 등록해야 합니다.

만약 모델이 존재하지 않는다면 model 패키지를 생성하고 위 사진과 같이 정보를 작성합니다.

 

본 예제에서는 XML mapper 파일을 mybatis라는 패키지 안에서 관리할 것이기 때문에 mapper-locations 항목의 설정을 잘 기억합니다.

 

4. mapper.xml 작성

applications.properties

 

mapper.xml은 DB 쿼리문을 관리하며 DB와 상호작용하는 파일입니다.

2번 항목에서 applications.properties 파일내  mapper-locations 설정을 com/example/demo/mybatis/**/*.xml로 정했습니다.

 

 

패키지를 생성하는 위치는 com.example.demo로 클래스 패스이므로 주의해야합니다.

com.example.demo.mybatis 패키지에 SalaryMapper.xml파일을 생성합니다.

DB에 있는 내용을 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.example.demo.mapper.SalaryMapper">
	<select id="getSalary" resultType="SalaryModel">
		SELECT * FROM SALARY;
	</select>
</mapper>

 

mapper 태그의 namespace는 아직은 생성하지 않은 Mapper 인터페이스를 의미합니다.

(다음 항목에서 생성합니다.)

 

resultType은 이전 포스팅에서 생성한 SalaryModel을 그대로 이용했습니다.

 

5. Mapper Interface 구현

com.example.demo 패키지에 mapper 패키지를 작성하고 SalaryMapper.java 파일을 생성합니다.

그리고 아래의 내용을 작성합니다.

@Repository
@Mapper
public interface SalaryMapper {
	List<SalaryModel> getSalary();
}

 

SalaryMapper 객체가 class가 아닌 interface 인 것에 주의해 주세요.

getSalary 메서드를 통해 쿼리문 관리하는 mapper.xml에 접근해 데이터베이스와 상호 작용하므로 SalaryMapper.xml 파일의 select 태그에서 지정한 id 값과 같아야합니다.

 

6. Service Class 작성

com.example.demo 패키지에 service라는 이름의 패키지를 생성하고 그 안에 SalaryService.java를 생성합니다.

그리고 아래의 내용을 작성합니다.

 

@Service
public class SalaryService {
	@Autowired
	public SalaryMapper mapper;
	
	public List<SalaryModel> getSalary(){
		return mapper.getSalary();
	}
}

 

이 클래스는 컨트롤러에서 Mysql에 접근하기 위한 첫 번째 관문이 됩니다.

해당 객체는 싱글톤으로 사용되어야 하기 때문에 @Service 어노테이션을 붙여 Bean 객체로 만듭니다.

그리고 5번 항목에서 구현한 SalaryMapper 인터페이스를 @Autowired를 통해 객체를 주입합니다.

 

그리고 반환형 List<SalaryModel> 형태로 DB 정보를 컨트롤러에서 받을 수 있도록 getSalary() 메서드를 작성합니다.

 

이제 컨트롤러로 돌아와 DB와 상호작용 해 보겠습니다.

 

7. DB 데이터 호출

HomeController에 goHome 메서드의 내용을 아래와 같이 재 정의합니다.

 

@Controller
public class HomeController {

	@Autowired
	SalaryService salaryService;
	
	@RequestMapping(value = "/home", method=RequestMethod.GET)
	public ModelAndView goHome(HttpServletRequest request) {
		ModelAndView mav = new ModelAndView();
		
		List<SalaryModel> salaryList = salaryService.getSalary();
		
		mav.addObject("salaryList", salaryList);
		mav.setViewName("content/home.html");
		
		return mav;
	}
}

 

@Autowired를 통해 SalaryService 객체를 주입하고, getSalary() 메서드를 통해 맵퍼를 거쳐 DB 정보를 획득한 다음 view로 보내는 코드입니다.

 

전에 작성해 두었던 templates/content/home.html 파일에 아마 아래와 같은 코드가 작성되어있을 겁니다.

 

<div layout:fragment="content" class="content">
    <h2>This is Content</h2>
    <hr>
    <table border="1">
        <tr>
            <th>id</th>
            <th>name</th>
            <th>email</th>
        </tr>
        <th:block th:each="salary : ${salaryList}">
            <tr>
                <td th:text="${ salary.id }"></td>
                <td th:text="${ salary.name }"></td>
                <td th:text="${ salary.email }"></td>
            </tr>
        </th:block>
    </table>
</div>

위 코드는 thymeleaf로 작성되었습니다. 만약 JSP를 사용한다면 그에 맞게 수정해주어야합니다.

 

작성했다면, localhost:8080/home으로 접속해 DB에 저장된 값을 제대로 호출하고 있는지 확인합니다.

 

정상적으로 값을 받아오고 있음을 확인했습니다.

 

그런데, DB에서 값을 제대로 받아오고 있는지를 콘솔 로그에서 보여주고 있지 않습니다.

이 상태로는 개발하는데 많은 불편함이 있으니 다음 포스팅에서는 쿼리문에 대한 로그 출력에 대해 알아보겠습니다.