일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- MYSQL
- exception
- 스프링
- 스프링 시큐리티
- Spring Security
- request
- http
- git
- OOP
- 스프링부트
- aspect
- proxy pattern
- response
- 트랜잭션
- Interceptor
- network
- 인터셉터
- mybatis
- aop
- 객체지향프로그래밍
- RestControllerAdvice
- SQL
- Spring
- java
- 관점지향프로그래밍
- Redis
- 자바
- 디자인패턴
- Filter
- spring boot
- Today
- Total
장쫄깃 기술블로그
[Spring - DB] 1. HikariCP를 이용한 MySQL DB 연결하기 본문
들어가며
기존에 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 라우팅을 하는 기능을 구현해 볼 것이다.