1. MyBatis
- MyBatis: Sql Mapping Framework라고 표현됨, Sql Mapping이란 SQL의 실행 결과를 객체 지향으로 매핑해준다는 뜻
- MyBatis 사용 시, 기존 SQL을 그대로 사용할 수 있고 다음의 장점이 존재
- PreparedStatement / ResultSet의 처리: 기존 프로그램 작성 시 하나씩 처리해야 하는 파라미터나 ResultSet의 getXXX()를 MyBatis가 알아서 처리해 주어 많은 양의 코드를 줄일 수 있음
- Connection / PreparedStatement / ResultSet의 close() 처리: MyBatis와 스프링을 연동해서 사용하는 방식을 이용하면 자동으로 close() 처리 가능
- SQL의 분리: MyBatis를 사용하면 별도의 파일이나 어노테이션 등을 이용해서 SQL을 선언, 파일을 이용하는 경우 SQL을 별도의 파일로 분리해서 운영 가능
1) MyBatis와 스프링의 연동 방식
- MyBatis는 단독으로 실행이 가능하지만, 스프링 프레임워크는 MyBatis와 연동을 쉽게 처리할 수 있는 라이브러리와 API를 제공
- MyBatis를 단독으로 개발하고 스프링에서 DAO를 작성해서 처리하는 방식
- 기존 DAO에서 SQL 처리를 MyBatis를 이용하는 구조
- 완전히 MyBatis와 스프링 프레임워크를 독립적인 존재로 바라보고 개발
- MyBatis와 스프링을 연동하고 Mapper 인터페이스만 이용하는 방식
- 스프링과 MyBatis 사이에 'mybatis-spring'이라는 라이브러리 이용
- 스프링이 데이터베이스 전체를 처리
- MyBatis는 일부 기능 개발에만 활용하는 방식
- 개발 시에는 Mapper 인터페이스라는 방식을 이용해서 인터페이스만으로 모든 개발이 가능한 방식
- MyBatis를 단독으로 개발하고 스프링에서 DAO를 작성해서 처리하는 방식
- MyBatis를 위한 라이브러리들
- 스프링 관련: spring-jdbc, spring-tx
- MyBatis 관련: mybatis, mybatis-spring
dependencies {
...
// spring 관련 라이브러리
implementation group: 'org.springframework', name: 'spring-jdbc', version: '5.3.19'
implementation group: 'org.springframework', name: 'spring-tx', version: '5.3.19'
// MyBatis 관련 라이브러리
implementation group: 'org.mybatis', name: 'mybatis', version: '3.5.6'
implementation group: 'org.mybatis', name: 'mybatis-spring', version: '2.0.6'
}
- MyBatis를 위한 스프링의 설정 - SqlSessionFactory
- MyBatis를 이용하기 위해 스프링에서 설정해둔 HikariDataSource를 이용해서 SqlSessionFactory라는 Bean을 설정
<!-- root-context.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context = "http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
<context:component-scan base-package = "org.zerock.springex.sample"></context:component-scan>
...
<!-- 이 부분 추가 -->
<bean id = "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean">
<property name = "dataSource" ref = "dataSource" />
</bean>
<!-- 여기까지 -->
</beans>
실습
1) Mapper 인터페이스 활용하기
- MyBatis는 SQL 파일을 별도로 처리할 수 있지만, 인터페이스와 어노테이션만으로도 처리 가능
- 프로젝트에 mapper라는 패키지 구성 > 현재 시간을 처리하는 TimeMapper 인터페이스 선언
// TimeMapper
package org.zerock.springex.mapper;
import org.apache.ibatis.annotations.Select;
public interface TimeMapper {
@Select("select now()")
String getTime();
}
- 데이터베이스의 현재 시각을 문자열로 처리하도록 구성
- @Select 어노테이션으로 쿼리 작성 가능(';' 사용 x)
- 작성된 인터페이스를 매퍼 인터페이스라고 하며, root-context.xml에 어떤 매퍼 인터페이스 설정했는지 등록해야함
<!-- root-context.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans ...
xmlns:mybatis = "http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
...
<mybatis:scan base-package = "org.zerock.springex.mapper"></mybatis:scan>
</beans>
- 테스트 코드를 통해 확인
- Test > java > org.zerock.springex > mapper 패키지 > TimeMapperTests
// TimeMapperTests
package org.zerock.springex.sample.mapper;
import lombok.extern.log4j.Log4j2;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.zerock.springex.mapper.TimeMapper;
@Log4j2
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/root-context.xml")
public class TimeMapperTests {
// required가 fales이면 해당 객체를 주입 받지 못하더라도 예외가 발생 x
@Autowired(required = false)
private TimeMapper timeMapper;
@Test
public void testGetTime() {
log.info(timeMapper.getTime());
}
}
- MyBatis와 스프링을 연동하고 매퍼 인터페이스를 활용하는 방식은 개발자가 실제 동작하는 클래스와 객체를 생성하지 않고, 스프링에서 자동 생성되는 방식 이용
- 스프링에서 자동 생성되어 개발자가 직접 코드를 수정할 수 없다는 단점이 있지만, 인터페이스만으로 개발을 완료할 수 있다는 장점
2) XML로 SQL 분리하기
- SQL을 @Select 어노테이션으로 써도 되지만, SQL이 길어지면 처리가 복잡해지고, 어노테이션이 변경되면 프로젝트 전체를 다시 빌드하는 작업이 필요하기 때문에 단순 파일(XML)로 사용하는 것이 편리
- XML과 매퍼 인터페이스 결합 과정
- 매퍼 인터페이스 정의하고 메서드 선언
- 해당 XML 파일 작성(파일이름과 매퍼 인터페이스 이름 같게), <select>와 같은 태그 이용해서 SQL 작성
- <select>, <insert> 등 태그에 id 속성 값을 매퍼 인터페이스의 메서드 이름과 같에 작성
- main > org.zerock.springex > mapper > TimeMapper2 파일 생성
// TimeMapper2
package org.zerock.springex.mapper;
public interface TimeMapper2 {
String getNow();
}
- main > source > mappers 패키지 생성 > TimeMapper2.xml 파일 생성(파일 이름을 매퍼 인터페이스와 같게)
<!-- TimeMapper2.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 = "org.zerock.springex.mapper.TimeMapper2">
<!-- select의 id 속성값을 매터 인터페이스의 메서드 이름과 같게 설정 -->
<!-- select 태그는 반드시 resultType이나 resultMap 속성을 지정해야 함 -->
<!-- resultType은 select문이 결과를 어떤 타입으로 처리할 지에 대한 설정 -->
<select id = "getNow" resultType = "string">
select now()
</select>
</mapper>
- 마지막으로 root-context.xml 파일의 MyBatis 설정에 XML 파일들을 인식하도록 설정을 추가
<!-- root-context.xml -->
...
<bean id = "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean">
<property name = "dataSource" ref = "dataSource" />
<!-- mapperLocations는 XML 매퍼 파일의 위치 -->
<property name = "mapperLocations" value = "classpath:/mappers/**/*.xml"></property>
</bean>
...
- 테스트 코드로 정상적으로 동작하는지 확인
// TimeMapperTests
package org.zerock.springex.sample.mapper;
import lombok.extern.log4j.Log4j2;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.zerock.springex.mapper.TimeMapper2;
@Log4j2
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/root-context.xml")
public class TimeMapperTests {
@Autowired(required = false)
private TimeMapper2 timeMapper2;
@Test
public void testNow() {
log.info(timeMapper2.getNow());
}
}
'back-end > Java' 카테고리의 다른 글
[자바 웹 개발 워크북] 4.4 - 스프링 Web MVC 구현하기(1) (0) | 2023.02.09 |
---|---|
[자바 웹 개발 워크북] 4.3 - 스프링 Web MVC 기초 (0) | 2023.01.17 |
[자바 웹 개발 워크북] 4.1 - 의존성 주입과 스프링 (0) | 2023.01.12 |
[자바 웹 개발 워크북] 3.3 - 리스너 (0) | 2023.01.11 |
[자바 웹 개발 워크북] 3.2 - 사용자 정의 쿠키 (1) | 2023.01.11 |