장쫄깃 기술블로그

[Spring - DB] 1. HikariCP를 이용한 MySQL DB 연결하기 본문

Spring Framework/Spring - DB

[Spring - DB] 1. HikariCP를 이용한 MySQL DB 연결하기

장쫄깃 2022. 6. 27. 23:40
728x90


들어가며


기존에 SpringBoot에선 tomcat-jdbc를 기본 DataSource로 제공했다. 하지만 2.0부터 HikariCP가 기본으로 변경되었다.(참고)

HikariCP는 이전 버전에서도 많은 사람들이 설정을 변경해서 사용했을 정도로 인기가 많았다.

이번 게시글에선 HikariCP의 DataSource 정보를 설정하는 방법에 대해서 알아보려고 한다. 더 나아가 다음 게시글에선 HikariCP를 이용하여 Transaction Read-Only 적용 시 Master / Slave DB 라우팅하는 방법까지 가보려고 한다.

 

 

1. Dependency 추가


<Gradle>

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'mysql:mysql-connector-java'
	implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	
	implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16'
}

 

MySQL을 사용하기에 MySQL Connector를 추가했다.

MyBatis-Spring을 추가하여 MyBatis 환경을 구성했다.

 

DB 로그를 확인하기 위해 log4jdbc 라이브러리를 사용하였다.

 

 

2. application.yml 설정


spring:
  datasource:
    hikari:
      driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
      jdbc-url: jdbc:log4jdbc:mysql://localhost:3306/test_master?characterEncoding=UTF-8
      username: root
      password: 1234

 

기본적으로 MySQL에 대한 JDBC 설정이다. 위에서 설명했듯 추후에 DB 로그를 확인하기 위해 log4jdbc 라이브러리를 사용하였다.

 

 

3. DataSource Config 구현


import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

@Configuration
public class DataSourceConfig {
	
	// application.yml의 설정 정보를 토대로 HikariCP 설정
	@Bean
	@ConfigurationProperties(prefix = "spring.datasource.hikari") // 읽어올 설정 정보의 prefix 지정
	public HikariConfig hikaryConfig() {
		return new HikariConfig();
	}
	
	// Connection Pool을 관리하는 DataSource 인터페이스 객체 선언
	@Bean
	public DataSource dataSource() {
		return new HikariDataSource(hikaryConfig());
	}
	
	// SqlSessionTemplate에서 사용할 SqlSession을 생성하는 Factory
	@Bean
	public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
		/*
		 * MyBatis는 JdbcTemplate 대신 Connection 객체를 통한 질의를 위해서 SqlSession을 사용한다.
		 * 내부적으로 SqlSessionTemplate가 SqlSession을 구현한다.
		 * Thread-Safe하고 여러 개의 Mapper에서 공유할 수 있다.
		 */
		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		
		// MyBatis Mapper Source
		// MyBatis의 SqlSession에서 불러올 쿼리 정보
		Resource[] res = new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*Mapper.xml");
		bean.setMapperLocations(res);
		
		// MyBatis Config Setting
		// MyBatis 설정 파일
		Resource myBatisConfig = new PathMatchingResourcePatternResolver().getResource("classpath:mybatis-config.xml");
		bean.setConfigLocation(myBatisConfig);
		
		return bean.getObject();
	}
	
	// DataSource에서 Transaction 관리를 위한 Manager 클래스 등록
	@Bean
	public DataSourceTransactionManager transactionManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}
}

 

application.yml에서 설정한 정보를 토대로 HikariCP를 설정한다.

SqlSessionFactory에 HikariCP의 DataSource, MyBatis Mapper 경로, MyBatis 설정파일 경로를 설정한다.

 

 

4. mybatis-config.xml 구현


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

<configuration>
	<settings>
		<setting name="mapUnderscoreToCamelCase" value="true" />
		<setting name="callSettersOnNulls" value="true"/>
	</settings>
</configuration>

 

MyBatis 설정 정보이다.

 

mapUnderscoreToCamelCase 설정으로 언더바 스코어 방식의 데이터를 자동으로 카멜케이스 방식으로 받아오게 했다.

(예를 들어, test_nm -> testNm)

 

callSettersOnNulls 설정으로 컬럼값이 null이더라도 누락이 되지 않도록 했다.

 

 

5. JDBC 로그 설정구현


<logback-spring.xml>

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT"
		  class="ch.qos.logback.core.ConsoleAppender">
	<encoder>
		<pattern>%boldMagenta(%d{MM-dd HH:mm:ss}) [%boldYellow(%-5level)] %cyan(%logger{5}.%M) - %msg %n</pattern>
	</encoder>
</appender>
<logger name="jdbc" level="OFF" />
<logger name="jdbc.sqlonly" level="INFO" />
<logger name="jdbc.sqltiming" level="OFF" />
<logger name="jdbc.audit" level="OFF" />
<logger name="jdbc.resultset" level="OFF" />
<logger name="jdbc.resultsettable" level="OFF" />
<logger name="jdbc.connection" level="OFF" />
<root level="INFO">
	<appender-ref ref="STDOUT" />
</root>

<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

<root level="info">
	<appender-ref ref="CONSOLE"/>
</root>
</configuration>

 

console창에 출력되는 로그에 대한 설정과 위에서 언급했던 DB 로그에 대한 설정 정보이다.

 

<appender> 안에 <pattern>은 내 콘솔창에 로그가 어떤 방식으로 출력될지를 결정한다.

참고 : https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.logging

 

<logger> 항목들을 통해 어떤 DB 로그를 출력할 지 결정한다.

  • jdbc : log4jdbc 옵션 설정
  • jdbc.sqlonly : sql문 로깅 여부
  • jdbc.sqltiming : 쿼리문 수행 시간 로깅 여부
  • jdbc.audit : ResultSet 외 모든 JDBC 호출 정보 로깅 여부
  • jdbc.resultset, jdbc.resultsettable : ResultSet 포함 모든 JDBC 호출 정보 로깅 여부
  • jdbc.connection : connection open close 로깅 여부

 

<log4jdbc.log4j2.properties>

log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
log4jdbc.dump.sql.maxlinelength=0

 

해당 설정파일들을 추가하면 다음과 같이 로그가 출력된다.

 

 

6. MyBatis Mapper 구현


해당 경로상의 TestMapper.xml과 TestMapper.java를 구현한다. TestMapper.xml은 DataSource 구현 시 설정했던 MyBatis Mapper 경로와 일치시킨다.

 

<TestMapper.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="com.jdh.dsTest.model.dao.TestMapper">
	<select id="selectTest" resultType="String">
		select test_nm from test_table;
	</select>
</mapper>

 

<TestMapper.java>

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface TestMapper {
	public String selectTest() throws Exception;
}

 

DB를 조회할 수 있는 간단한 테스트 코드를 작성한다.

 

 

7. Service 구현


@Service
public class TestService {
	@Autowired TestMapper testMapper;
	
	public String getTest() throws Exception {
		return testMapper.selectTest();
	}
}

 

 

Mapper를 통해 DB에서 데이터 조회를 요청할 Service를 구현한다.

 

 

8. Test


@Slf4j
@SpringBootTest
public class TestController {
	@Autowired TestService service;
	
	@Test
	public void test() throws Exception {
		log.info(service.getTest());
	}
}

 

테스트를 해보면 데이터를 정상적으로 조회하는 것을 알 수 있다.

 

 

 

정리하며


이번 게시글에서는 Spring Boot와 HikariCP를 이용하여 간단하게 MySQL과 연동해보는 테스트를 진행했다. 다음 게시글에선 원래의 목적이었던 Transaction Read-Only 시에 자동으로 Master/Slave DB 라우팅을 하는 기능을 구현해 볼 것이다.

728x90