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과 인터페이스 메서드를 추가로 정의한다.