본문 바로가기

Spring Framework

[Spring] spring에 mybatis 적용하기

반응형

 

이번 글은 spring에 mybatis를 적용하는 방법에 대해 정리해보려고 합니다.

 

먼저 mybatis는 무엇이고 어떤 역할을 하는지 알아보겠습니다.

 

Mybatis란?

Mybatis는 자바에서 JDBC를 통해 DB에 접근하여 SQL 쿼리를 수행할 수 있도록 지원하는 개발 프레임워크입니다. 

제가 JDBC를 위해 자바에서 사용할 수 있는 JPA보다 Mybatis를 좋아하는 이유는 Mybatis장점 때문입니다.

 

Mybatis의 장점

  • 복잡한 SQL 쿼리를 수행하는데 유리하다.
  • 자바와 SQL 쿼리를 분리할 수 있다.

 

제가 강조하고 싶은 장점은 첫 번째 복잡한 SQL 쿼리를 수행하는데 장점이 있다는 점입니다. 

 

이렇게 복잡한 쿼리가 있다고 했을 때 JPA로 작성하는 것은 힘든 작업 일 수 있습니다. (왜 힘든지에 대해서는 JPA에 대해 알아야 하기 때문에 생략하겠습니다.. 죄송합니다.)

<select id="autoAssignmentCoury" parameterType="Payload" resultType="Payload">
    <![CDATA[
        SELECT 
            COURY_SEQUENCE,
            REPLACE(COURY_FROM_ADDRESS, ' ****', '') AS COURY_FROM_ADDRESS,
            COURY_FROM_NAME,
            REPLACE(COURY_TO_ADDRESS, ' ****', '') AS COURY_TO_ADDRESS,
            COURY_TO_NAME,
            CASE
                WHEN WEIGHT >= 0 AND WEIGHT <= 2 THEN 'A'
                WHEN WEIGHT >= 3 AND WEIGHT<= 5 THEN 'B'
                WHEN WEIGHT >= 6 AND WEIGHT <= 15 THEN 'C'
                WHEN WEIGHT >= 16 THEN 'D'
            END AS WEIGHT,
            CASE
                WHEN SIZE>= 0 AND SIZE <= 80 THEN 'A'
                WHEN SIZE>= 81 AND SIZE <= 100 THEN 'B'
                WHEN SIZE>= 101 AND SIZE <= 120 THEN 'C'
                WHEN SIZE>= 121 THEN 'D'
            END AS SIZE,
            CATEGORY,
            REPLACE(AREA, ',', '') AS AREA,
            DATE_FORMAT(CONCAT(EXPRESS_DATE, EXPRESS_TIME) , '%Y-%m-%d/%H') AS COURY_DATE
        FROM COURY
        WHERE COURY_ASSIGNMENT = 'N'
        AND DATE_FORMAT(CONCAT(EXPRESS_DATE, EXPRESS_TIME) , '%Y-%m-%d/%H') BETWEEN '2022-05-02/19' AND '2022-05-03/19'
        AND COURY_TO_ADDRESS like '%마포구%'
        AND AREA LIKE CONCAT('%', #{area}, '%')
    ]]>
    <if test='priority != null and priority != ""'>
        <![CDATA[
            ORDER BY ${priority} ASC
        ]]>	
    </if>
    <![CDATA[
        LIMIT ${count}
    ]]>
</select>

 

위의 코드는 Mybatis를 사용하기 때문에 Java 코드와 분리되어 xml에 작성된 순수 SQL의 예시입니다. 한눈에 보기에도 복잡하지만 순수 SQL 만을 다룰 수 있기 때문에 SQL만을 사용하기 때문에 자바의 문법에 제약을 받지 않고 쿼리를 작성할 수 있다는 장점이 있습니다. (자바로부터 독립적이라는 의미는 xml파일만을 떼어내어 다른 프로젝트에도 사용할 수 있다는 것을 의미하겠죠?)

 

Spring에 Mybatis 적용하기

 

이제는 mybatis를 스프링 프로젝트에 적용하는 방법에 대해 정리해보려고 합니다. 

 

1. MvcConfig.java

@EnableWebMvc 
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
    
	@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/").setCachePeriod(31556926);
    }

    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }    
    
    // Connection Pool 
 	@Bean
 	public DataSource dataSource() {
 		HikariConfig hikariConfig = new HikariConfig();
 		hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver"); // mysql driver 사용
 		hikariConfig.setJdbcUrl("jdbc:mysql://localhost:[Port]]/[DBName]]?serverTimezone=UTC");
 		hikariConfig.setUsername(Username);
 		hikariConfig.setPassword(Password);
 		
 		return new HikariDataSource(hikariConfig);
 	}
 	
 	// mybatis
 	@Bean
 	public SqlSessionFactory sessionFactory() throws Exception {
 		SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
 		sessionFactoryBean.setDataSource(dataSource());
 		
 		PathMatchingResourcePatternResolver pmrpr = new PathMatchingResourcePatternResolver();
 		Resource resource_path = pmrpr.getResource("classpath:sql-map-config.xml");
 		
 		sessionFactoryBean.setConfigLocation(resource_path);
 		return sessionFactoryBean.getObject();
 	}
 	
 	@Bean
 	public SqlSessionTemplate sqlSession() throws Exception {
        return new SqlSessionTemplate(sessionFactory());
 	}
}

 

첫 번째 파일은 Mybatis를 위한 Config(구성) 자바 파일입니다. 

  • addResourceHandlers: 리소스 등록 및 핸들러를 관리하는 객체인 ResourceHandlerRegistry를 통해 리소스 위치와 이 리소스와 매칭 될 url을 등록합니다. 
  • configureDefaultServletHandling : 스프링 컨테이너와 관련된 메서드이므로 mybatis와 관련 없음
  • datasource : Datasouce 객체는 DB와 관계된 커넥션 정보를 담고 있으며 빈으로 등록하여 인자로 넘겨줍니다. 이 과정을 통해 Spring은 DataSource로 DB와의 연결을 획득할 수 있습니다. 

 

여기까지는 리소스 파일 위치 설정, 스프링 컨테이너 설정, DB 연결 작업이었기 때문에 Mybatis와 관련이 깊지 않습니다. 다음에 나오는 메서드는 Mybatis와 관련이 많기 때문에 따로 정리했습니다.

 

// mybatis
@Bean
public SqlSessionFactory sessionFactory() throws Exception {
    SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
    sessionFactoryBean.setDataSource(dataSource());

    PathMatchingResourcePatternResolver pmrpr = new PathMatchingResourcePatternResolver();
    Resource resource_path = pmrpr.getResource("classpath:sql-map-config.xml");

    sessionFactoryBean.setConfigLocation(resource_path);
    return sessionFactoryBean.getObject();
}

@Bean
public SqlSessionTemplate sqlSession() throws Exception {
    return new SqlSessionTemplate(sessionFactory());
}

 

 

Mybatis에서는 SqlSession을 생성하기 위해 SqlSessionFactory를 사용합니다. 여기서 SqlSession이란 SQL 실행이나 트랜잭션 관리를 실행하는 클래스를 의미합니다. SqlSessionFactory는 SqlSession을 생성하는 역할을 담당합니다. 

 

메서드에서는 먼저 사용할 datasource를 DI 받고 PathMatchingResourcePatternResolver라는 Resource 인터페이스를 구현한 클래스를 통해 classpath에 위치한 resource를 가져올 수 있습니다. 미리 생성해둔 sql-map-config.xml이라는 mybatis설정 파일을 연결하는 작업입니다. 

 

마지막으로 SqlSessionFactory를 빈으로 등록하고 마무리합니다. 

 

SqlSessionTemplate은 SqlSession을 구현하고 코드에 SqlSession을 대체하는 역할을 합니다. SqlSessionTemplate은 필요한 시점에 세션을 닫고, 커밋하거나 롤백하는 것을 포함한 세션의 생명주기를 관리합니다. 또한 Mybatis 예외를 스프링의 DataAccessException으로 변환하는 작업 또한 처리합니다. 

 

JdbcTemplate처럼 자주 변하지 않는 공통된 부분을 template으로 분리했던 것과 유사한 방식이라고 생각하시면 될 것 같습니다. 

 

[Spring] JdbcTemplate

이번글은 Spring 프레임워크의 JdbcTemplate에 대해 알아 보려고 합니다. JdbcTemplate를 사용하는 목적과 사용방법에 대해 자세히 알아보겠습니다. 1. 변하는 것과 변하지 않는것 이전에 다뤘던 IoC/DI는

jminc00.tistory.com

 

 

2. sql-map-config

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<!-- MYBATIS RESOURCE CONFIGURATION -->
<configuration>
	<mappers>
		<mapper resource="mybatis/user/user_mapper.xml"/>				
	</mappers>
</configuration>

 

두 번째는 Mybatis의 설정 파일입니다. 여기서 configuration/mappers 내에 있는 mapper 태그를 이용해서 비즈니스 로직 별로 xml파일을 분리해서 공통된 관심사별로 SQL을 따로 작성하여 관리할 수 있습니다. mappers 태그 내에 등록된 mapper 들만 사용할 수 있습니다. 

 

3. user_mapper.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="mybatis.user.user_mapper">
	<insert id="registerUser" parameterType="Payload">
		<![CDATA[
			INSERT INTO USER 
				(
					USER_ID,
					USER_PASSWORD,
					USER_NAME,
					USER_PHONENUM
				)
			VALUES
				(
					#{USER_ID},
					#{USER_PASSWORD},
					#{USER_NAME},
					#{USER_PHONENUM}
				)
		]]>
	</insert>
</mapper>

 

세 번째는 mapper 태그에 연결되어 등록된 user_mapper.xml 파일입니다. 위의 코드 예시처럼 sql를 작성하여 사용할 수 있습니다. 이때 ParameterType이 Payload로 되어있는데 이건 제가 따로 만든 HashMap <String, String> 클래스를 상속받아 만든 클래스 객체입니다. parameterType은 기본 자료형이나, 래퍼런스형, Collection객체 등을 사용할 수 있으며 Mybatis의 Alias를 통해 parameter를 설정할 수 있습니다. 

 

지금 까지 mybatis를 스프링에 적용하는 방법에 대해 간단히 알아봤습니다. 

mybatis의 핵심은 SQl을 저장해두는 전용 포맷을 가진 독립적인 파일로 분리하는 곳에 있습니다. 잘못된 부분이 있다면 댓글을 통해 알려주시면 감사하겠습니다!

반응형

'Spring Framework' 카테고리의 다른 글

QueryDSL 바로 알기  (0) 2024.03.31
[Spring] PSA(Portable Service Abstraction)  (1) 2022.11.05
[Spring] 예외를 처리하는 방법  (0) 2022.11.01
[Spring] JdbcTemplate  (0) 2022.10.22
[Spring] TDD란?  (0) 2022.10.14