자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API *자료를 쿼리, 업데이트하는 방법 제공
일반적인 데이터 연동과정은 웹 애플리케이션에서 필요할 때마다 데이터베이스에 연결하는 방식이다.
이런식으로 필요할 때마다 연동해서 작업할 경우 동시에 몇 천, 몇 만명이 커넥션을 맺고 푸는 작업을 할 수 있기 때문에 데이터베이스 연결에 시간이 많이 걸리는 문제가 발생한다.
이러한 문제점을 해결하기 위해 현재 웹 애플리케이션이 실행됨과 동시에 연동할 데이터베이스와의 연결을 미리 설정해준다.
그리고 필요할 때마다 미리 연결해놓은 상태를 이용해 빠르게 데이터베이스와 연동하여 작업한다.
*Connection Pool : CP : 미리 데이터베이스와 연결시킨 상태를 유지하는 기술
자바에서는 기본적으로 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 구성.
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" 를 추가하면 자동으로 추가된다.
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를 권장한다. |
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>
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
[js] 함수 내 인자로 함수넣기 (0) | 2022.07.27 |
---|---|
Springboot logback 설정 (0) | 2022.07.20 |
HikariCP 연동시 에러 발생 (0) | 2022.07.20 |
스프링 부트 mysql 데이터베이스 연동 (0) | 2022.07.19 |
스프링 부트 스케줄러 @EnableScheduling @Scheduled (0) | 2022.07.18 |