Springboot + Mybatis 연동

조성권·2021년 12월 18일
1
post-thumbnail

오늘은 SpringbootMybatis를 연동하는 방법에 대해 알아보도록 하겠다.

1. 기술스펙

  • SpringBoot (JAVA 11, Maven)
  • Thymeleaf
  • MySQL

2. 연동 작업

2-1. Spring Initializr를 통한 프로젝트 생성

  • 의존성 주입된 pom.xml 전체 코드
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.6.1</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>mybatisStudy</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>mybatisStudy</name>
	<description>for my mybatis study</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.2.0</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

2-2. MySQL, Mybatis를 위한 property 환경 설정

전체 application.properties

# mysql config
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mytestdb?serverTimezone=UTC&characterEncoding=UTF-8
spring.datasource.username={본인DB's username}
spring.datasource.password={본인DB's password}

# mybatis config
mybatis.type-aliases-package=com.example.mybatisStudy.vo
mybatis.mapper-locations=mybatis/mapper/**/*.xml

소스 분석

2-2-1. MySQL 설정

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

JDBC 드라이버 클래스의 이름 지정 (위 클래스는 MySQL JDBC 드라이버 클래스)

spring.datasource.url=jdbc:mysql://localhost:3306/{본인db명}?serverTimezone=UTC&characterEncoding=UTF-8

본인 DB의 IP와 스키마 이름 지정 (나머지는 그대로 사용하고 {본인db명} 부분만 본인 db로 변경)

spring.datasource.username={본인DB's username}
spring.datasource.password={본인DB's password}

본인 DB의 usernamepassword 기입


2-2-2. Mybatis 설정

mybatis.type-aliases-package={mapper resultType}

DB의 조회 결과 데이터를 담을 클래스 package 지정 (=resultType)

mybatis.mapper-locations={mapper 경로}

mapper가 위치한 경로 설정

2-3. Back 로직 작성

Controller

  • MemberController.java
package com.example.mybatisStudy.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.mybatisStudy.service.MemberService;
import com.example.mybatisStudy.vo.MemberVo;

@Controller
@RequestMapping("/")
public class MemberController {
	
	@Autowired
	private MemberService memberService;
	
	@RequestMapping(value="/index")
	public String index(Model model) {
		
		List<MemberVo> memberList = memberService.getAllMember();
		System.out.println("size: " + memberList.size());
		
		
		model.addAttribute("memberList",memberList);
		return "index";
	}
}

  • 주요 소스분석
List<MemberVo> memberList = memberService.getAllMember();

-> MemberVo 객체 리스트를 List형태로 불러온다.

model.addAttribute("memberList",membetList);

-> Thymeleaf를 통해 memberList 데이터를 가져와 뿌려주기 위해 Model 사용


Service

  • MemberService.java
// Service.java
package com.example.mybatisStudy.service;

import java.util.List;

import com.example.mybatisStudy.vo.MemberVo;


public interface MemberService {
	public List<MemberVo> getAllMember();
}
  • MemberServiceImpl.java
// ServiceImpl.java
package com.example.mybatisStudy.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.mybatisStudy.repository.MemberRepository;
import com.example.mybatisStudy.service.MemberService;
import com.example.mybatisStudy.vo.MemberVo;

@Service
public class MemberServiceImpl implements MemberService{
	
	@Autowired
	private MemberRepository memberRepository;
	
	@Override
	public List<MemberVo> getAllMember(){
		return memberRepository.getAllMember();
	}
}

  • 주요 소스분석

현재 프로젝트는 Mybatis 연동을 위한 단순 기능만을 제공하므로 Service단은 다른 로직 없이 바로 Dao로 넘긴다.

@Override
public List<MemberVo> getAllMember(){
	return memberRepository.getAllMember();
}

Repository

  • MemberRepository.java
package com.example.mybatisStudy.repository;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import com.example.mybatisStudy.vo.MemberVo;

@Mapper
public interface MemberRepository {
	List<MemberVo> getAllMember();
}
  • 주요 소스분석
@Mapper
public interface MemberRepository {
	List<MemberVo> getAllMember();
}

기존 Spring MVC는 SqlSession, SqlSessionFactory와 같은 클래스를 통해 설정하고 Dao단에서 selectOne과 같은 함수를 call하여 처리했다.

SpringBoot의 @Mapper를 사용하게 되면 application.properties에서 설정한 경로를 바탕으로 알아서 쿼리 xml 파일과 매핑해주기 때문에 위의 일련의 과정을 생략할 수 있다.

  • Vo
  • MemberVo.java
package com.example.mybatisStudy.vo;

public class MemberVo {
	private String user_no;
	private String user_nm;
	private String user_id;
	
	
	public String getUser_no() {
		return user_no;
	}
	public void setUser_no(String user_no) {
		this.user_no = user_no;
	}
	public String getUser_nm() {
		return user_nm;
	}
	public void setUser_nm(String user_nm) {
		this.user_nm = user_nm;
	}
	public String getUser_id() {
		return user_id;
	}
	public void setUser_id(String user_id) {
		this.user_id = user_id;
	}
}

lombok을 사용해서 코드를 간결히 처리할 수도 있지만 이번 프로젝트는 lombok 사용이 주요 목표가 아니니 getter/setter를 각각 만들어주었다.

  • Mybatis XML
  • member.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.example.mybatisStudy.repository.MemberRepository">
	<select id="getAllMember" resultType="MemberVo">
		SELECT user_no, user_nm, user_id FROM MEMBER_INFO
	</select>
</mapper>
  • 주요 소스분석
<?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">

위 부분은 Mybatis를 사용하기 위한 기본 설정부분으로 똑같이 기입해주면 된다.

<mapper namespace="com.example.mybatisStudy.dao.MemberDao">
	<select id="getAllMember" resultType="MemberVo">
		SELECT user_no, user_nm, user_id FROM MEMBER_INFO
	</select>
</mapper>

namespace부분은 @Mapper와 매핑시키기 위한 경로를 기입하는 부분으로
본인이 @Mapper 어노테이션으로 Mapper를 만들어놓은 경로를 입력해주면 된다.

resultType은 원래 전체 패키지경로를 입력해줘야하지만 앞서 application.properties에서

mybatis.type-aliases-package=com.example.mybatisStudy.vo

위와 같이 상위 패키지명을 기입해줬기 때문에 해당 경로 하위 객체명만 기입해주면 된다.

2-4. Thymeleaf를 통한 Front 구성

  • 전체 소스
<!DOCTYPE html>
<html>
<head lang="en" xmlns:th="http://thymeleaf.org">
<meta charset="UTF-8">

<style>
	table {
		font-family: arial, sans-serif;
		border-collapse: collapse;
		width: 100%;
	}
	
	td, th{
		border: 1px solid black;
		text-align: left;
	}
	
	tr:nth-child(even){
		background-color:#dddddd;
	}
</style>

<title>Insert title here</title>
	</head>
<body>
	<h1>회원 리스트</h1>
	
	<table>
		<thead>
			<tr>
				<th>회원번호</th>
				<th>아이디</th>
				<th>이름</th>
			</tr>
		</thead>
		
		<tbody>
			<tr th:each="member : ${memberList}">
			 	<td><span th:text="${member.user_no}"></span></td>
				<td><span th:text="${member.user_id}"></span></td>
				<td><span th:text="${member.user_nm}"></span></td>
			</tr>
		</tbody>
	</table>
</body>
</html>
  • 주요 소스분석
<tbody>
	<tr th:each="member : ${memberList}">
	 	<td><span th:text="${member.user_no}"></span></td>
		<td><span th:text="${member.user_id}"></span></td>
		<td><span th:text="${member.user_nm}"></span></td>
	</tr>
</tbody>

Thymeleaf를 사용하게 되면 Back단에서 Model 객체를 통해 넘긴 값을 바로 받아서 사용할 수 있다.
th:each문을 통해 해당 객체 리스트를 받아오고 th:text를 통해 객체 내부 값을 출력하도록 만든다.

Thymeleaf는 이번 주제와 상관없는 부분이기 때문에 이에 대한 문법은 추후, 따로 작성해보도록 하겠다.

2-5. MySQL Table 구조

3. 실행 결과

profile
천천히, 완벽히 배워나가고자 하는 웹 서비스 엔지니어

1개의 댓글

comment-user-thumbnail
2022년 11월 7일

프로그래밍 설계도 있을까요?

답글 달기