본문 바로가기

SQL

MyBatis 기본 설정에서 Spring Boot에서 적용까지


개요

JPA와 같은 ORM 기술은 꾸준히 공부해왔지만 MyBatis는 사용해 볼 기회가 없었는데 학습을 위해 강의와 블로그를 보면서 MyBatis 설정부터 간단한 예제까지 정리하는 글

 

연습 환경 Spring Boot 2.6.5, Jdk11, H2 DB

MyBatis란?

마이바티스는 개발자가 지정한 SQL, 저장프로시저 그리고 몇가지 고급 매핑을 지원하는 퍼시스턴스 프레임워크이다.

 

JDBC와 비슷한 SQL Mapper로 JDBC에서 제공하는 대부분의 기능을 활용할 수 있고

중요 특징은 XML을 활용해서 SQL을 쉽게 작성하고 동적 쿼리를 편리하게 작성할 수 있다는 점이다.

JDBC vs MyBatis

JDBC

String sql = "update item " +
"set item_name=:itemName, price=:price, quantity=:quantity " +
"where id=:id";

 

MyBatis

<update id="update">
	update item
	set item_name=#{itemName},
		price=#{price},
		quantity=#{quantity}
	where id = #{id}
</update>

 

같은  update쿼리지만 MyBatis는 XML을 활용해서 Query를 더욱 가독성 좋게 작성할 수 있다.

 

아래부턴 실제로 환경을 구성해 MyBatis를 활용해본다.

 


MyBatis설정

MyBatis를 활용하기 약간의 설정이 필요하다.

 

build.gradle 의존성 추가

    //MyBatis 추가
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
    //H2 데이터베이스 추가
    runtimeOnly 'com.h2database:h2'

 

MyBatis와 H2 DB를 활용하기 위해 build.gradle에 의존성을 추가한다.

 

application.properties 설정 추가

#DB설정
spring.application.name=redis-study
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.username=sa

#MyBatis
mybatis.type-aliases-package=hello.itemservice.domain
mybatis.configuration.map-underscore-to-camel-case=true
logging.level.hello.itemservice.repository.mybatis=trace

 

mybatis.type-aliases-package

  • 마이바티스에서 타입 정보를 사용할 때는 패키지 이름을 적어주어야 하는데, 여기에 명시하면 패키지 이름을 생략할 수 있다.
  • 지정한 패키지와 그 하위 패키지가 자동으로 인식된다.

mybatis.configuration.map-underscore-to-camel-case

  • _(언더바)로 나오는 내용을 camel-case로 변경해준다.

logging.level.hello.itemservice.repository.mybatis=trace

  • 실행되는 쿼리 로그를 확인한다.

 


MyBatis 적용

설정이 끝났으니 이름과 비밀번호로 구성된 간단한 User 클래스를 만들어서 기능들을 실행해보자

 

user 클래스

@Data
public class User {
    private long id;
    private String username;
    private String password;

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
}

mapper 생성

@Mapper
public interface UserMapper {

    long save(User user);

    Optional<User> findById(long id);

    List<User> findAll();
}

 

mapper어노테이션을 붙여야 MyBatis에서 인식할 수 있다.

 

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="hello.itemservice.repository.mybatis.UserMapper">

  <insert id="save" useGeneratedKeys="true" keyProperty="id">
    insert into user (username, password)
    values (#{username}, #{password})
  </insert>

  <select id="findById" resultType="User">
    select id, username, password
    from user
    where id = #{id}
  </select>

  <select id="findAll" resultType="User">
    select id, username, password
    from user
  </select>

</mapper>

 

해당 도메인과 연관된 sql을 xml파일로 만들어서 resources 경로에 저장한다.

그 과정에서 패키지 위치를 mapper 인터페이스와 잘 맞추고 namespace도 확인해야 한다 안그러면 오류가 발생한다

경로예시

java/hello/itemservice/repository/mybatis/UserMapper.java

resources/hello/itemservice/repository/mybatis/UserMapper.xml

 

repository 생성

@Repository
@RequiredArgsConstructor
public class UserRepository {
    private final UserMapper userMapper;
    
    public long save(User user) {
        return userMapper.save(user);
    }
    
    public Optional<User> findById(long id) {
        return userMapper.findById(id);
    }
    
    public List<User> findAll() {
        return userMapper.findAll();
    }

}

 

repository는 mapper의 기능을 위임하는 역할을 한다.

 

controller, service 생성

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

    private final UserService userService;

    @PostMapping("/join")
    @ResponseBody
    public long join(@RequestBody UserDto userDto) {
        return userService.save(userDto);
    }

    @GetMapping("/{id}")
    public String findOne(@PathVariable long id) {
        User findUser = userService.findById(id);
        return findUser.getUsername();
    }

    @GetMapping("")
    public List<User> allUsers() {
        return userService.findAll();
    }
}

 

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;

    public long save(UserDto userDto) {

        User user = new User(userDto.getUsername(), UUID.randomUUID().toString()+userDto.getPassword());
        return userRepository.save(user);
    }

    public User findById(long id) {
        User user = userRepository.findById(id).orElseThrow();
        return user;
    }

    public List<User> findAll() {
        return userRepository.findAll();
    }
}

 

api 테스트 용으로 간단하게 구현했다.

 

이제 Post 맨을 통해 api 테스트를 한다.

 

Postman 테스트

join()

findAll()

findOne()

 

Postman을 서서 테스트 해보면 작성한 기능들이 잘 작동하고 있음을 확인할 수 있다.

 

DB


느낀점

Jpa만 공부하다 보니 아직 MyBatis 사용이 어색한 느낌이 많이 있다.

 

xml을 오해 query를 작성하는 부분이나 mapper를 활용하는 부분이 특히 그렇다.

 

그래도 기초를 맛봤으니 앞으로도 많이 해보면서 익숙해지지 않을까라는 희망이 있다.

 

다행히 MyBatis는 한글판 매뉴얼이 매우 잘 되어있고 따라가다 보면 쉽게 공부할 수 있을 것 같다.

 

꾸준히 열심히 공부하자!

 

 

작성에 도움이 된 내용들

https://mybatis.org/mybatis-3/ko/java-api.html

 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-2

 

스프링 DB 2편 - 데이터 접근 활용 기술 강의 - 인프런

백엔드 개발에 필요한 DB 데이터 접근 기술을 활용하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., 백엔드 개발자

www.inflearn.com

 

https://velog.io/@kkj53051000/MyBatis%EB%9E%80-%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C

 

MyBatis란? - 공식문서

> 공식문서를 단순 정리한 게시글입니다. ( mybatis > 시작하기 ) 마이바티스란? 마이바티스란 개발자가 지정한 SQL, 저장 프로시저(Stored Procedure) 그리고 몇가지 고급 매핑을 지원하는 프레임워크입

velog.io