Spring Boot 3.x 환경에서 MyBatis-Plus 연동하기

Spring Boot 3.2 기반 프로젝트에 MyBatis-Plus를 통합하는 방법을 알아본다.

의존성 설정

MyBatis-Plus를 사용하면 MyBatis 의존성을 별도로 추가할 필요가 없다. 다음 의존성들을 pom.xml에 추가한다.

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.4.0</version>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    <version>3.5.6</version>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.6</version>
</dependency>

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>

환경별 설정 분리

application.yml에서 활성화할 프로파일을 지정한다.

spring:
  profiles:
    active: local

MyBatis-Plus 상세 설정

application-local.yml에 데이터베이스 연결과 MyBatis-Plus 설정을 구성한다.

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/appdb?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Seoul&autoReconnect=true
    username: admin
    password: secret

mybatis-plus:
  mapper-locations: classpath:mapper/**/*.xml
  type-aliases-package: com.example.app.*.domain
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      logic-delete-value: 1
      logic-not-delete-value: 0
      logic-delete-field: is_deleted

코드 자동 생성

mybatis-plus-generator를 활용하여 Entity, Mapper, Service 계층을 자동으로 생성할 수 있다.

생성기 클래스 작성

아래와 같이 GeneratorRunner.java를 작성한다.

package com.example.app.codegen;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.fill.Column;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class GeneratorRunner {

    private static final String DB_HOST = "localhost";
    private static final String DB_PORT = "3306";
    private static final String DB_SCHEMA = "appdb";
    private static final String JDBC_URL = String.format(
        "jdbc:mysql://%s:%s/%s?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Seoul&autoReconnect=true",
        DB_HOST, DB_PORT, DB_SCHEMA
    );
    private static final String DB_USERNAME = "admin";
    private static final String DB_PASSWORD = "secret";

    public static String readInput(String prompt) {
        Scanner reader = new Scanner(System.in);
        System.out.printf("▶ %s: ", prompt);
        if (reader.hasNext()) {
            String value = reader.next().trim();
            if (!value.isEmpty()) {
                return value;
            }
        }
        throw new MybatisPlusException(prompt + " 값을 올바르게 입력하세요");
    }

    public static void main(String[] args) {
        String projectRoot = System.getProperty("user.dir");
        
        FastAutoGenerator.create(JDBC_URL, DB_USERNAME, DB_PASSWORD)
            .globalConfig((scanner, config) -> config
                .author(readInput("작성자 이름"))
                .commentDate("yyyy-MM-dd")
                .outputDir(projectRoot + "/src/main/java")
                .disableOpenDir())
            .packageConfig((scanner, config) -> config
                .parent(readInput("기본 패키지명")))
            .strategyConfig((scanner, config) -> config
                .addInclude(parseTables(readInput("테이블명 (쉼표로 구분, 전체: all)")))
                .entityBuilder()
                .enableLombok()
                .addTableFills(
                    new Column("created_at", FieldFill.INSERT),
                    new Column("updated_at", FieldFill.INSERT_UPDATE)
                )
                .build())
            .execute();
    }

    private static List<String> parseTables(String input) {
        return "all".equalsIgnoreCase(input) 
            ? Collections.emptyList() 
            : Arrays.asList(input.split(","));
    }
}

메인 메서드를 실행하면 콘솔에서 작성자, 패키지명, 테이블명을 입력받아 파일을 생성한다. user.dir은 프로젝트 루트 디렉터리를 가리킨다.

Mapper 스캔 설정

생성된 Mapper 인터페이스를 스프링이 인식하도록 설정 클래스를 추가한다.

package com.example.app.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.example.app.infrastructure.mapper")
public class MyBatisPlusConfiguration {
}

기본 CRUD 활용

MyBatis-Plus는 기본적인 CRUD 메서드를 제공한다. Service 구현체에서 baseMapper나 상속받은 메서드를 사용할 수 있다.

package com.example.app.application.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.app.domain.model.User;
import com.example.app.infrastructure.mapper.UserMapper;
import org.springframework.stereotype.Service;

@Service
public class UserService extends ServiceImpl<UserMapper, User> {

    public User fetchById(Long userId) {
        return baseMapper.selectById(userId);
    }

    public User fetchByEmail(String email) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, email);
        return baseMapper.selectOne(wrapper);
    }
}

커스텀 쿼리가 필요한 경우 Mapper XML과 인터페이스 메서드를 추가로 정의한다.

태그: MyBatis-Plus Spring Boot 3 java MySQL Code Generator

5월 24일 22:33에 게시됨