개발 환경 설정 및 툴 사용법

Spring Boot with Mybatis : 스프링부트 Mybatis 설정 + User CRUD (FULL 버전)

letsDoDev 2024. 8. 31. 22:02

-해당 게시물은 실제 CRUD 까지 적용하는 것을 기록한 게시물로

- mybatis 에 대한 설정만 간략하게 보고싶다면

https://letsdodev.tistory.com/200

 

Spring Boot with Mybatis : 스프링부트 Mybatis 설정 (요약)

#1 Dependency 추가해주자 (case. 신규 프로젝트)-  만약 사용하여 신규 프로젝트를 만든 다면 - 아래 이미지처럼 파란 박스  Dependecy 추가   #1 Dependency 추가해주자 (case. 진행 중인 프로젝트) ※ 버

letsdodev.tistory.com

- 위 게시물로 확인하자


 

오늘은 스프링 부트와 mybatis 설정을 진행하고 테스트할 것이다.

- 스프링 이니셜라이저로 다음과 같이 프로젝트 생성

-  CRUD 테스트할 테이블 생성 및 샘플데이터 INSERT

CREATE DATABASE mybatishandler;

use mybatishandler;

CREATE TABLE user(
id BIGINT AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
password VARCHAR(20) NOT NULL,
role VARCHAR(10) DEFAULT 'USER',
PRIMARY KEY(id)
);

INSERT INTO user(name, password, role)
VALUES('admin', '0000', 'ADMIN');

INSERT INTO user(name, password)
VALUES('user1', '0000');

INSERT INTO user(name, password)
VALUES('user2', '0000');

INSERT INTO user(name, password)
VALUES('user3', '0000');

- 샘플 데이터 INSERT 잘 되었나 확인

 

- application.yml 

spring:
  application:
    name: setting
# mysql db 설정
  datasource:
    url: "jdbc:mysql://localhost/refactorlibrary"
    username: "root"
    password: ${MYSQL_ROOT_PASSWORD} # 시스템 환경 변수에 'MYSQL_ROOT_PASSWORD' 라고 저장되어있는 값 사용
    driver-class-name : com.mysql.cj.jdbc.Driver

 

- 프로젝트 구조 및 패키지 경로 ( 대충 각자 마음대로 작성하면 됨, 프로젝트 다 완성 후 모습)

- 내 pc의 jdk 버전이 21 이라는 것을 까먹고 작업을 시작하고 있었다... jdk 22를 추가로 설치해주었다ㅠㅠ

- gradle 로 빌드하고 SpringBootApplication run class 실행시켜보기

good!~

- application.yml 에 mybatis 설정 추가 ★

spring:
  application:
    name: setting
# mysql db 설정
  datasource:
    url: "jdbc:mysql://localhost/mybatishandler"
    username: "root"
    password: ${MYSQL_ROOT_PASSWORD} # 시스템 환경 변수에 'MYSQL_ROOT_PASSWORD' 라고 저장되어있는 값 사용
    driver-class-name : com.mysql.cj.jdbc.Driver

# mybatis mapper.xml 경로 설정    
mybatis:
    mapper-locations: classpath:mapper/*.xml
    type-aliases-package: com.mybatis.setting.mapper
# mapper.xml 의  nameSpace가 c"om.mybatis.setting.mapper" 로 시작하는 매퍼.xml 들은 -> (sqlSession 경로)
# src/resuorces/  "mapper/*.xml" 을 뒤적거려서 찾겠다.

 

- UserDto, UserRequestDto, UserResponseDto

 ㄴ UserDto

package com.mybatis.setting.dto.user;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class UserDto {

    private long id;
    private String name;
    private String password;
    private String role;

    @Builder
    public UserDto(long id, String name, String password, String role) {
        this.id = id;
        this.name = name;
        this.password = password;
        this.role = role;
    }
}

 ㄴ UserRequestDto

package com.mybatis.setting.dto.user;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class UserRequestDto {

    private long id;
    private String name;
    private String password;
    private String role;

    @Builder
    public UserRequestDto(long id, String name, String password, String role) {
        this.id = id;
        this.name = name;
        this.password = password;
        this.role = role;
    }
}

 ㄴ UserResponseDto

package com.mybatis.setting.dto.user;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class UserResponseDto {

    private long id;
    private String name;
    private String password;
    private String role;

    @Builder
    public UserResponseDto(long id, String name, String password, String role) {
        this.id = id;
        this.name = name;
        this.password = password;
        this.role = role;
    }
}

 

- UserDao, UserDaoImpl

 ㄴ UserDao

package com.mybatis.setting.dao;

import com.mybatis.setting.dto.user.UserDto;

import java.util.List;

public interface UserDao {

    public List<UserDto> findAllUsers(); // 전체 유저 조회
    public int insertUser(UserDto user); // 신규 유저 추가
    public UserDto findUserById(long id); // id로 유저 정보 조회
    public UserDto findUserByNameAndPassword(String name, String password); // name 과 password로 유저 정보 조회
    public int updateUserById(UserDto user); // 특정 유저 정보 update
    public int deleteUserById(long id);
}

 

 ㄴ UserDaoImpl

package com.mybatis.setting.dao;

import com.mybatis.setting.dto.user.UserDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Repository
@RequiredArgsConstructor
public class UserDaoImpl implements UserDao{

    // 방법 1 sqlSession 을 사용하는 방법
    private final SqlSessionFactory sqlSessionFactory;

    // 방법 2 sqlSessionTemplate 을 사용하는 방법 -> 내가 채택한 방법
    private final SqlSessionTemplate sqlSessionTemplate;

    // src/resources/mapper 경로의 UserMapper.xml 의 namespace 이다.
    private static String nameSpace = "com.mybatis.setting.mapper.UserMapper";

    @Override
    public List<UserDto> findAllUsers() {
        // 방법 1
        /*
        try (SqlSession sqlSession = sqlSessionFactory.openSession();){
            return sqlSession.selectList(nameSpace + ".findAllUsers");
        } catch (Exception e) {
            log.error(e.getLocalizedMessage());
            throw e;
        }
         */

        // 방법 2
        return sqlSessionTemplate.selectList(nameSpace + ".findAllUsers");
    }

    @Override
    public int insertUser(UserDto user) {
        // 방법 1
        /*
        try (SqlSession sqlSession = sqlSessionFactory.openSession();){
             return sqlSession.insert(nameSpace + ".insertUser", user);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage());
            throw e;
        }
         */

        // 방법 2
        return sqlSessionTemplate.insert(nameSpace + ".insertUser", user);
    }

    @Override
    public UserDto findUserById(long id) {
        // 방법 1
        /*
        try (SqlSession sqlSession = sqlSessionFactory.openSession();){
             return sqlSession.selectOne(nameSpace + ".findUserById", (int) id));
        } catch (Exception e) {
            log.error(e.getLocalizedMessage());
            throw e;
        }
         */

        // 방법 2
        return sqlSessionTemplate.selectOne(nameSpace + ".findUserById", (int) id);
    }

    @Override
    public UserDto findUserByNameAndPassword(String name, String password) {

        Map<String, String> userMap = new HashMap<>();
        userMap.put("name", name);
        userMap.put("password", password);

        // 방법 1
        /*
        try (SqlSession sqlSession = sqlSessionFactory.openSession();){
             return sqlSession.selectOne(nameSpace + ".findUserByNameAndPassword", userMap);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage());
            throw e;
        }
         */

        // 방법 2
        return sqlSessionTemplate.selectOne(nameSpace + ".findUserByNameAndPassword", userMap);
    }

    @Override
    public int updateUserById(UserDto user) {
        // 방법 1
        /*
        try (SqlSession sqlSession = sqlSessionFactory.openSession();){
             return sqlSession.update(nameSpace + ".updateUserById", user);
        } catch (Exception e) {
            log.error(e.getLocalizedMessage());
            throw e;
        }
         */

        // 방법 2
        return sqlSessionTemplate.update(nameSpace + ".updateUserById", user);
    }

    @Override
    public int deleteUserById(long id) {
        // 방법 1
        /*
        try (SqlSession sqlSession = sqlSessionFactory.openSession();){
             return sqlSession.update(nameSpace + ".deleteUserById", (int) id));
        } catch (Exception e) {
            log.error(e.getLocalizedMessage());
            throw e;
        }
         */

        // 방법 2
        return sqlSessionTemplate.delete(nameSpace + ".deleteUserById", (int) id);
    }
}

 

★ ★ ★

- UserMapper.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">

<!-- src/main/resources/mapper/UserMapper.xml -->
<!-- sqlSession 으로 가지고 올 때 사용되는 일종의 key 라고 보면 됨-->
<mapper namespace="com.mybatis.setting.mapper.UserMapper">

    <select id="findAllUsers" resultType="com.mybatis.setting.dto.user.UserDto">
        SELECT
            ID,
            NAME,
            PASSWORD,
            ROLE
        FROM USER
    </select>

    <select id="findUserById" parameterType="java.lang.Integer" resultType="com.mybatis.setting.dto.user.UserDto">
        SELECT
            ID,
            NAME,
            PASSWORD,
            ROLE
        FROM USER
        WHERE
            ID = #{id}
    </select>

    <select id="findUserByNameAndPassword" parameterType="map" resultType="com.mybatis.setting.dto.user.UserDto">
        SELECT
            ID,
            NAME,
            PASSWORD,
            ROLE
        FROM USER
        WHERE
            NAME = #{name} AND
            PASSWORD = #{password}
    </select>

    <insert id="insertUser" parameterType="com.mybatis.setting.dto.user.UserDto">
        INSERT INTO USER(NAME, PASSWORD, ROLE)
        VALUES(#{name}, #{password}, #{role})
    </insert>

    <update id="updateUserById" parameterType="com.mybatis.setting.dto.user.UserDto">
        UPDATE USER SET
            NAME = #{name},
            PASSWORD = #{password},
            ROLE = #{role}
        WHERE
            ID = #{id}
    </update>

    <delete id="deleteUserById" parameterType="java.lang.Integer">
        DELETE FROM USER
        WHERE
            ID = #{id}
    </delete>

</mapper>

 

 

- UserController.java (테스트 할 URI 정의)

package com.mybatis.setting.controller;

import com.mybatis.setting.dto.user.UserRequestDto;
import com.mybatis.setting.dto.user.UserResponseDto;
import com.mybatis.setting.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/user")
public class UserController {

    private final UserService userService;

    // 전체 유저 조회
    @GetMapping("/all")
    public List<UserResponseDto> findAllUsers() {
        return userService.findAllUsers();
    }

    // 유저 신규 추가
    @PostMapping("/add")
    public UserResponseDto insertUser(@RequestBody UserRequestDto user) {
        return userService.insertUser(user);
    }

    // 특정 유저 조회 - 검색 조건 : id
    @GetMapping("/one")
    public UserResponseDto findUserById(@RequestParam long id) {
        return userService.findUserById(id);
    }

    // 특정 유저 조회 - 검색 조건 : name, password
    @PostMapping("/one")
    public UserResponseDto findUserByNameAndPassword(@RequestBody Map<String, String> userMap) {
        return userService.findUserByNameAndPassword(userMap.get("name"), userMap.get("password"));
    };

    // 특정 유저 정보수정 - 검색 조건 : id  , 수정 내용 대상 : name, password, role
    @PutMapping("/one")
    public int updateUserById(@RequestBody UserResponseDto user) {
        return userService.updateUserById(user);
    }

    // 특정 유저 삭제 - 검색 조건 id
    @DeleteMapping("/one")
    public UserResponseDto deleteUserById(@RequestParam long id) {
        return userService.deleteUserById(id);
    }
}

 

- 테스트 결과

 ㄴ 전체 유저 조회

 

 

ㄴ 유저 신규 추가

 

 

 

ㄴ 특정 유저 조회 - 검색 조건 : id

 

 

 

ㄴ 특정 유저 조회 - 검색 조건 : name, password

 

ㄴ 특정 유저 정보수정 - 검색 조건 : id,  수정 내용 대상 : name, password, role

 

ㄴ 특정 유저 삭제 - 검색 조건 : id