[Mybatis] 마이바티스란 무엇이고 간단한 사용법에 대해서
MyBatis
란 자바 프로그래밍 언어용 데이터베이스 맵핑 툴(SQL Mapper)
이다. 이를 사용하여, SQL 쿼리를 보다 쉽게 데이터베이스에 연결하고 실행할 수 있다. ‘MyBatis’를 사용하는 주된 이유는 SQL 문을 프로그램 코드와 분리하여 관리할 수 있다는 점이다. 이렇게 하면, SQL 문을 좀더 유연하게 관리하고, 코드의 가독성과 유지 보수성을 향상시킬수 있다. 예를 들어, 데이터베이스 테이블에 데이터를 추가, 조회, 수정, 삭제하는 작업을 SQL 파일에 별도로 작성하고, 이 SQL 파일을 MyBatis를 통해 자바 코드와 연결한다.
‘MyBatis’의 가장 큰 장점은 SQL을 XML에 편리하게 작성할 수 있고 또 동적 쿼리를 매우 편리하게 작성할 수 있다는 점이다.
💡 SQL Mapper: SQL을 직접 작성해 해당 SQL문과 Object의 필드를 매핑하여 데이터를 다루는 Persistence Framework이다.
- Persistence: 프로그램이 종료되더라도 사라지지 않는 데이터 특성을 말한다.
- Persistence Framework(영속성 프레임워크): 데이터베이스와 연동되는 시스템을 빠르게 개발하고 안정적인 구동을 보장해주는 프레임워크
MyBatis 기본 동작
SQL 매핑 파일 생성
: SQL 문과 이를 처리할 매핑 정보를 XML 파일이나 어노테이션 형태로 작성한다.설정 파일 작성
: 데이터베이스 연결 정보와 매핑 파일의 위치 등의 설정을 포함한다.세션 생성
: MyBatis는 SQL을 실행하기 위해 ‘SqlSession’이라는 객체를 사용한다. 이 객체는 설정 파일을 기반으로 생성된다.SQL 실행
SqlSession을 사용하여 SQL 매핑 파일에 정의된 SQL문을 실행한다.
MyBatis 설정하기
의존성 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Maven
<dependencies>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.x.x</version>
</dependency>
<!-- 데이터베이스 드라이버 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.x.x</version>
</dependency>
<!-- 기타 필요한 의존성 추가 -->
</dependencies>
// Gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc' //MyBatis 추가
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
}
데이터 소스 설정
데이터베이스 연결에 필요한 DataSource를 설정한다. 이는 데이터베이스 URL, Username, Password 등의 정보를 포함한다. Spring Boot를 사용하는 경우 ‘application.properties’또는 ‘application.yml’파일에 이러한 속성을 정의할 수 있다.
1
2
3
4
5
6
7
spring.datasource.url=jdbc:h2:tcp://localhost/~/hello
spring.datasource.username=sa
spring.datasource.password=
#MyBatis
mybatis.type-aliases-package=hello.service.domain
mybatis.configuration.map-underscore-to-camel-case=true
- mybatis.type-aliases-package
- 마이바티스에서 타입 정보를 사용하기 위해서 패키지 이름을 명시 해야한다. 해당 속성에 명시하면 패키지 이름을 생략할 수 있다.
- 여러 위치를 지정하려면
,
또는;
로 구분하면 된다.
- mybatis.configuration.map-underscore-to-camel-case
- 언더바(_)를 카멜로 자동 변경해주는 기능을 활성화 한다.
MyBatis 설정: SqlSessionFactoryBean
구성
MyBatis의 SQL 세션 팩토리를 설정한다. 이는 MyBatis의 ‘SqlSessionFactoryBean’을 사용하여 구성된다. ‘SqlSessionFactoryBean’은 MyBatis 설정 파일의 경로, 데이터 소스, 마이바티스 매퍼 파일의 위치 등을 설정한다.
💡 'mybatis-spring-boot-starter'를 사용할 경우 'SqlSessionFactory'는 자동으로 구성되지만, 특정 경우에 개발자가 추가적인 설정을 제공할 필요가 있을 수 있다. 이 경우, Java구성 클래스에서 '@Bean' 어노테이션을 사용하여 'SqlSessionFactroy'빈을 명시적으로 정의할 수 있다.
Spring과 통합된 MyBatis 설정하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration // 스프링 구성 파일 명시
public class MyBatisConfig {
@Autowired
private DataSource dataSource; // 데이터베이스 연결 정보(URL, USERNAME ...)를 포함한 객체
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
// SqlSessionFactoryBean: 'SqlSessionFactory'를 생성하기 위한 헬퍼 클래스, 이 객체는 SQL 세션을 생성하고, MyBatis와 데이터베이스 간의 상호 작용을 관리
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource); // DataSource 설정, 데이터베이스 연결을 관리
sessionFactory.setMapperLocations(
new PathMatchingResoucePatternResolver().getResouces("classpaht:mappers/*.xml")
); // 매퍼 파일들의 위치를 지정, 이 파일들은 SQL 쿼리와 자바메소드를 매핑하는 데 사용
return sessionFactory.getObject();
}
}
Spring 프레임워크와의 통합
: 이 설정은 Spring의 의존성 주입 기능을 활용하여 ‘DataSource’를 자동으로 주입하고, Spring 컨테이너에 ‘SqlSessionFactory’빈을 등록한다.매퍼 위치 설정
: MyBatis 매퍼 파일들의 위치를 지정한다. 이를 통해 SQL 매핑이 이루어진다.
매퍼 인터페이스 스캔: @MapperScan
사용
‘@MapperScan’ 어노테이션은 MyBatis 매퍼 인터페이스가 위치한 패키지를 지정한다. 이렇게 하면 Spring이 해당 패키지를 스캔하여 매퍼 인터페이스를 자동으로 찾아 빈으로 등록한다.
1
2
3
4
5
6
7
@SpringBootApplication
@MapperScan("com.hello.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(hello.class, args);
}
}
트랜잭션 관리자 설정: ‘DataSourceTransactionManager’사용
1
2
3
4
5
6
7
8
9
10
@Configuration
public class TransactionConfig {
@Autowired
private DataSource dataSource;
@Bean
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
}
DataSourceTransactionManager
: 이 클래스는 JDBC기반의 데이터베이스 트랜잭션 관리를 위한 Spring의 구현체이다. 이 객체는 주어진 ‘DataSource’를 사용하여 트랜잭션을 관리한다.
MyBatis 적용하기
데이터 저장 예시를 활용한 이해
Mapper Interface
MyBatis에서는 SQL 쿼리와 자바 메소드를 연결하는 매퍼 인터페이스를 정의한다.
1
2
3
4
5
package com.hello.mapper;
public interface HelloMapper {
void save(User user);
}
Mapper XML
매퍼 인터페이스의 각 메소드에 해당하는 SQL 쿼리를 정의하는 XML 파일을 작성한다.
1
2
3
4
5
6
7
<?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.hello.mapper.HelloMapper">
<insert id="save">
INSERT INTO users (name, email) VALUES (#{name}, #{email})
</insert>
</mapper>
해당 파일은 ‘resource/mappers’ 디렉토리에 저장되며, 이전에 설정한 ‘setMapperLocations’에서 이 위치를 지정하였다.
서비스 클래스
매퍼 인터페이스를 사용하여 실제 비즈니스 로직을 구현하는 서비스 클래스를 작성한다.
1
2
3
4
5
6
7
8
9
@Service
public class HelloService {
@Autowired
private HelloMapper helloMapper;
public void saveUser(User user) {
helloMapper.save(user);
}
}
컨트롤러
최종적으로, 사용자의 요청을 받아 서비스 로직을 호출하는 컨트롤러를 작성한다.
1
2
3
4
5
6
7
8
9
10
11
@RestController
@RequestMapping("/users")
public class HelloController {
@Autowired
private HelloService helloService;
@PostMapping
public void saveUser(@RequestBody User user) {
helloService.saveUser(user);
}
}
전체 흐름
- 클라이언트는 ‘/users’경로로 POST 요청을 보낸다.
- 컨트롤러가 요청을 받고, ‘HelloService’의 ‘saveUser’메소드를 호출한다.
- ‘HelloService’는 ‘HelloMapper’의 ‘save’ 메소드를 호출하여 데이터베이스에 사용자 정보를 저장한다.
- ‘save’메소드는 매퍼 XML에 정의된 SQL 쿼리를 실행한다.
기본 파라미터 바인딩: #{}
’#{}’ 구문은 SQL 쿼리 내에서 파라미터를 바인딩하는 데 사용된다. 이 구문을 사용하면 MyBatis가 자동으로 파라미터 값을 SQL 쿼리에 안전하게 삽입한다.
1
2
3
<select id="selectUser" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
해당 코드에서 ‘#{id}’는 메소드 호출 시 제공된 파라미터의 ‘id’값을 SQL 쿼리에 바인딩한다.
동적 SQL 구문
MyBatis는 동적 쿼리를 작성할 수 있는 여러 XML 태그를 제공한다. 이를 사용하면 SQL 쿼리를 보다 유연하게 작성할 수 있다.
<if>
: 특정 조건이 참일 때만 SQL의 일부를 포함시키고 싶을 때 사용한다.
1
2
3
4
5
6
7
8
<select id="selectUsersByName" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">
name = #{name}
</if>
</where>
</select>
여기서, ‘if test=”name != null”‘는 name 파라미터가 null이 아닐 경우에만 해당 조건을 쿼리에 포함시킨다.
<where>
: SQL 쿼리의 ‘WHERE’절을 동적으로 구성한다. ‘where’태그는 자동으로 앞에 오는 ‘AND’또는 ‘OR’키워드를 관리한다.
1
2
3
4
5
6
7
8
9
10
11
<select id="findUser" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">
name = #{name}
</if>
<if test="email != null">
AND email = #{email}
</if>
</where>
</select>
여기서 ‘where’태그는 필요한 경우에만 ‘whrer’절을 추가하고, 각 ‘if’조건 앞의 ‘AND’나 ‘OR’을 적절하게 관리한다.
<choose>, <when>, <otherwise>
: ‘if-else’ 또는 ‘switch’문과 유사하게 사용할 수 있다. 여러 조건 중 하나를 선택하여 실행한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<select id="findUserByStatus" resultType="User">
SELECT * FROM users
<where>
<choose>
<when test="status == 'ACTIVE'">
status = 'ACTIVE'
</when>
<when test="status == 'INACTIVE'">
status = 'INACTIVE'
</when>
<otherwise>
status = 'PENDING'
</otherwise>
</choose>
</where>
</select>
여기서 ‘choose’태그는 제공된 조건들 ‘when’중 하나를 선택하고, 해당 조건이 없을 경우 ‘otherwise’절을 사용한다.
<foreach>
: 컬렉션을 반복처리할 때 사용한다. 주로 ‘IN’절을 동적으로 생성할 때 유용하다.
1
2
3
4
5
6
7
8
<select id="selectUsersInList" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
여기서 ‘foreach’태그는 주어진 ‘list’ 컬렉션의 각 요소에 대해 반복적으로 SQL 조각을 생성한다.