상세 컨텐츠

본문 제목

Spring Boot MyBatis - MySQL - Hikari CP 연동

SPRING

by jeonghojin 2022. 7. 20. 13:53

본문

JDBC(Java Database Connectivity) :

자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API *자료를 쿼리, 업데이트하는 방법 제공

 

Database Connection Pool  : 

일반적인 데이터 연동과정은 웹 애플리케이션에서 필요할 때마다 데이터베이스에 연결하는 방식이다.

이런식으로 필요할 때마다 연동해서 작업할 경우 동시에 몇 천, 몇 만명이 커넥션을 맺고 푸는 작업을 할 수 있기 때문에 데이터베이스 연결에 시간이 많이 걸리는 문제가 발생한다.

이러한 문제점을 해결하기 위해 현재 웹 애플리케이션이 실행됨과 동시에 연동할 데이터베이스와의 연결을 미리 설정해준다.

그리고 필요할 때마다 미리 연결해놓은 상태를 이용해 빠르게 데이터베이스와 연동하여 작업한다.

*Connection Pool : CP :  미리 데이터베이스와 연결시킨 상태를 유지하는 기술

 

Spring Connection Pool : 

자바에서는 기본적으로 DataSource 인터페이스를 사용하여 커넥션풀을 관리한다.

Spring에서는 사용자가 직접 커넥션을 관리할 필요없이 자동화된 기법들을 제공한다.

* SpringBoot 2.0 이전에는 tomcat-jdbc 사용

* SpringBoot 2.0 이후부터 HikariCP 를 기본옵션으로 채택하고 있다.

* HikariCP는 가볍고 빠른 처리속도로 이점이 있다.

 


1. build.gradle 설정

2. application.properties 설정

3. mybatis 설정, Configuration 설정

4. Controller, Service, Mapper 구성.


1. build.gradle 설정

plugins {
    id 'org.springframework.boot' version '2.7.1'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}


repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation "org.springframework.boot:spring-boot-starter-jdbc"
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'mysql:mysql-connector-java'
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.4'
    implementation group: 'com.googlecode.log4jdbc', name: 'log4jdbc', version: '1.2'   // SQL Log
    implementation 'org.projectlombok:lombok'

    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.projectlombok:lombok'
    testAnnotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

HikariCP에 대해서 따로 추가할 필요 없이 "org.springframework.boot:spring-boot-starter-jdbc" 를 추가하면 자동으로 추가된다.


2. application.properties 설정

server.mode=dev
server.port=30003

#Database configuration
spring.datasource.hikari.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.hikari.url=jdbc:mysql:{URL}
spring.datasource.hikari.username={유저아이디}
spring.datasource.hikari.password={비밀번호}
#Hikari Options
spring.datasource.hikari.maximum-pool-size=5
spring.datasource.hikari.connection-timeout=5000
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.connection-init-sql=SET @enckey = '{암호키}'
spring.datasource.hikari.auto-commit=true

**HikariCP Options :

더보기
options example description
maximum-pool-size 10 휴한 connection과 사용중인 connection을 포함하여 pool의 크기를 설정하는 것이다. 기본값으로는 10을 가진다.
connection-timeout 5000 클라이언트가 pool의 connection을 기다리는 최대 시간(밀리초, ms)에 관한 설정으로, 기본값은 30000ms(30초)이고, 최소값은 250ms이다. 또한 만일 최대 시간을 넘으면 SQL Exception이 발생한다.
connection-init-sql SELECT 1  
validation-timeout 2000 valid 쿼리를 통해 커넥션이 유효한지 검사할 때 사용되는 timeout. 250ms가 설정될 수 있는 최솟값(default: 5000ms)
minimum-idle 10 pool에서 관리하는 최소 유휴 connection의 수에 관한 설정이다. 기본값으로 maximumPoolSize와 같은 값을 가진다.
idle-timeout 60000  connection이 유휴 상태로 남을 수 있는 최대시간(밀리초, ms)에 관한 설정이다. 기본값을호는 600000ms(10분)이고, 최소값으로는 10000ms(10초)를 가질 수 있다.
max-lifetime 1800000 connection의 최대 유지시간에 관한 설정이다. 이 시간이 지난 connection 중에서 사용중인 connection은 connection이 종료된 이후에 pool에서 제거가 된다. 기본값으로는 1800000ms(30분)를 가지고, 0으로 설정하게 되면 무한 수명을 의미한다. 
auto-commit true / false pool에서 반환된 connection의 기본 autoCommit에 관한 설정으로 기본값은 true 이다.

 

* mysql과 사용할 경우 권장 옵션

data-source-properties.cachePrepStmts true / false  cache 사용에 여부 대한 설정으로 true로 지정해야지 cache 관련 옵션들을 활성화 할 수 있다.
data-source-properties.prepStmtCacheSize 200 MySQL 드라이버가 연결당 cache할 statement의 수에 관한 설정이다. 기본값은 25이지만 250~500이 권장 설정이다.
data-source-properties.prepStmtCacheSqlLimit 2048 드라이버가 cache할 SQL 문의 최대 길이에 관한 설정이다. MySQL은 기본값으로 256을 가지고 권장 설정은 2048이다.
data-source-properties.useServerPrepStmts true / false MySQL의 최신 버전을 지원 받는 설정으로 큰 성능 향상을 제공받을 수 있기에 true를 권장한다.

3. mybatis 설정, Configuration 설정

Database Configuration : 

package com.example.databasetest.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

@Configuration
@PropertySource("classpath:config/application-dev.properties")
@MapperScan(basePackages = "com.example.databasetest.repository", sqlSessionFactoryRef = "sqlSessionFactory")
public class DatabaseConfiguration {


    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public HikariConfig hikariConfig() {
        return new HikariConfig();
    }

    @Bean(name="dataSource")
    public DataSource dataSource(HikariConfig hikariConfig) {
        return new HikariDataSource(hikariConfig);
    }

    @Bean(name="sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource, ApplicationContext applicationContext) throws Exception{

        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setConfigLocation(applicationContext.getResource("classpath:mybatis/mybatis-config.xml"));
        sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:mybatis/mappers/*Mapper.xml"));

        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name="sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception{
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

@Configuration : 스프링 컨테이너에 등록할 빈에 대한 설정파일임을 명시

@PropertySource : 설정파일에서 읽어올 설정 정보들의 경로를 지정

@Bean : 스프링 빈으로 등록

@ConfigurationProperties(prefix = "") : 읽어올 설정 정보의 prefix 지정

 

Mybatis config

더보기
<?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="cacheEnabled" value="false" />
        <setting name="useGeneratedKeys" value="true" />
        <setting name="defaultExecutorType" value="REUSE" />
        <setting name="callSettersOnNulls" value="true" />
        <setting name="lazyLoadingEnabled" value="false" />
    </settings>

    <typeAliases>
        <!--DTO, VO 작성.-->
        <typeAlias alias="User" type="com.example.databasetest.model.User" />
    </typeAliases>

   <!-- <typeHandlers>
        <typeHandler handler="com.example.databasetest.common.BigDecimalTypeHandler" />
    </typeHandlers>-->
</configuration>

4. Controller, Service, Mapper 구성.

더보기

 

Controller

package com.example.databasetest.controller;

import com.example.databasetest.model.User;
import com.example.databasetest.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;

@Controller
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @RequestMapping(value = "/users", method = RequestMethod.GET)
    public List<User> getUsers(){
        List<User> userList = userService.findAll();
        return userList;
    }
}

 

Service

package com.example.databasetest.service;

import com.example.databasetest.model.User;

import java.util.List;

public interface UserService {
    List<User> findAll();
}
package com.example.databasetest.service.impl;

import com.example.databasetest.model.User;
import com.example.databasetest.repository.UserMapper;
import com.example.databasetest.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    final private UserMapper userMapper;

    @Override
    public List<User> findAll() {
        return userMapper.findAll();
    }
}

 

Mapper

package com.example.databasetest.repository;

import com.example.databasetest.model.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public interface UserMapper {
    List<User> findAll();
}
<?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.example.databasetest.repository.UserMapper">

    <select id="findAll" resultType="User">
        SELECT seq, email, created_at FROM mercury.v_user
    </select>

</mapper>

 

 

 

 

 

참고: 

https://freedeveloper.tistory.com/250

 

[SpringBoot HikariCp] HikariCP 속성 설정 가이드

[HikariCp Preperty] https://effectivesquid.tistory.com/entry/HikariCP-세팅시-옵션-설명 http://blog.naver.com/PostView.nhn?blogId=hanajava&logNo=221570132498&parentCategoryNo=40&categoryNo=&viewDate=..

freedeveloper.tistory.com

 

관련글 더보기