Spring

[Spring] 데이터 베이스 연결 (feat. MariaDB, HikariCP)

allempty_sheep 2024. 8. 29. 09:01
반응형

 

tododb 라는 이름의 데이터 베이스를 생성

사용자 비밀번호는 todo / todo1234 로 설정한다.

 

CREATE USER todo@localhost IDENTIFIED BY 'todo1234';
GRANT ALL PRIVILEGES ON tododb.* TO todo@localhost;
FLUSH PRIVILEGES;

 

이후 워크벤치에 접속한다.

 

테이블을 만들어보자.

create table tbl_todo(
  tno int auto_increment primary key,
  title varchar(100) not null,
  dueDate date not null,
  finished tinyint default 0
);

 

이후 셀렉트가 잘 되는지 확인한다.

select * from tbl_todo;

 

모두 잘 된다면 데이터 베이스를 연결 해 보자.

 

ConnectionTests.java 파일을 하나 만들어 테스트 해보자.

package org.bigdata.controller;

import static org.junit.Assert.assertNotNull;

import java.sql.Connection;
import java.sql.DriverManager;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import lombok.extern.log4j.Log4j2;
import todo.TodoListController;

public class ConnectTests {
	
	private static final Logger logger = LoggerFactory.getLogger(TodoListController.class);

	@Test
	public void testConnection() throws Exception {
		Class.forName("org.mariadb.jdbc.Driver");
		
		Connection connection = DriverManager.getConnection(
				"jdbc:mariadb://localhost:3306/tododb",
				"todo",
				"todo1234"
				);
		
		// 데이터 베이스 연결 성공 여부
		assertNotNull(connection);
		logger.info("******************************");
		logger.info("* DB test connection success *");
		logger.info("******************************");
		
		connection.close();
	}
	
}

 

다음과 같이 나오면 연결이 된 것이다.

 

HikariCP 를 이용해서 코드를 짜보자.

pom.xml 에 라이브러리를 추가 해 준다.

		<!-- hikariCP -->
		<!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
		<dependency>
		    <groupId>com.zaxxer</groupId>
		    <artifactId>HikariCP</artifactId>
		    <version>5.0.0</version>
		</dependency>

 

해당 라이브러리를 이용하여 코드를 구성 해 준다.

코드를 싱글톤 패턴을 사용하여 객체를 하나만 생성 하도록 만들었다.

package todo.domain;

import java.sql.Connection;

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

public enum ConnectionUtil {
	
	INSTANCE;
	
	private HikariDataSource ds;
	
	private ConnectionUtil() {
		// TODO Auto-generated constructor stub
		// 히카리 cp 설정 객체
		HikariConfig config = new HikariConfig();
		
		config.setDriverClassName("org.mariadb.jdbc.Driver");
		config.setJdbcUrl("jdbc:mariadb://localhost:3306/tododb");
		config.setUsername("todo");
		config.setPassword("todo1234");
		// 캐시 처리 설정
		config.addDataSourceProperty("cachePrepStmts", true);
		// 캐시 처리 할 수 있는 sql 문장의 개수
		config.addDataSourceProperty("prepStntCacheSize", 250);
		config.addDataSourceProperty("prepStntCacheSqlLimit", 2048);
		
		ds = new HikariDataSource(config);
	}
	
	public Connection getConnecton() throws Exception {
		return ds.getConnection();
	}
}

 

해당 유틸을 이용하여 데이터베이스를 사용하는 함수를 만들어 볼 것이다.

유형은 두가지를 살펴 볼 것인데

첫번째는 어노테이션 없이, 두번째는 어노테이션을 사용하여 만들 것이다.

 

TodoDAO.java

package todo.dao;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import lombok.Cleanup;
import todo.domain.ConnectionUtil;
import todo.domain.TodoVO;

public class TodoDAO {
	public String getTime() {
		
		String now = null;
		
		// 괄호를 이용하면 객체를 사용 후 자동으로 클로즈 시켜준다. try ~ with resources 방식
		// 
		try (	Connection connection = ConnectionUtil.INSTANCE.getConnecton();
				PreparedStatement preparedStatement = connection.prepareStatement("select now()");
				ResultSet resultSet = preparedStatement.executeQuery();
				
				){
				resultSet.next();
				
				now = resultSet.getString(1);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return now;
	}
	
	public String getTime2() throws Exception {
		
		@Cleanup Connection connection = ConnectionUtil.INSTANCE.getConnecton();
		@Cleanup PreparedStatement preparedStatement = connection.prepareStatement("select now()");
		@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
		
		resultSet.next();
		
		String now = resultSet.getString(1);
		
		return now;
	}
}

 

위의 getTime 함수는 커넥션을 가져와 데이터 베이스와 연결 후 현재 시간을 가져온다.

이때 특이하게 try 구문에 () 괄호가 들어가 있는 것을 볼 수 있는데

이 괄호를 사용할 시 객체를 사용 후 자동으로 클로즈 시켜준다.

 

이를 어노테이션으로 구현한 것이 getTime2 함수이다.

 

그럼 이를 이용하여 데이터를 넣는 함수를 하나 만들어보자.

 

package todo.dao;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import lombok.Cleanup;
import todo.domain.ConnectionUtil;
import todo.domain.TodoVO;

public class TodoDAO {
	
	public void insert(TodoVO vo) throws Exception {
		String sql = "insert into tbl_todo (title, dueDate, finished) values (?,?,?)";
		
		@Cleanup Connection connection = ConnectionUtil.INSTANCE.getConnecton();
		@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(sql);
		
		preparedStatement.setString(1, vo.getTitle());
		preparedStatement.setDate(2, Date.valueOf(vo.getDueDate()));
		preparedStatement.setBoolean(3, vo.isFinished());
		
		preparedStatement.executeUpdate();
		
		System.out.println("insert vo");
	}
}

 

insert 함수를 만들었는데 인자로 TodoVo 형을 받는다.

 

TodoVo.java

package todo.domain;

import java.time.LocalDate;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@Builder
@ToString
// 모든 필드를 매개변수로 하는 생성자를 자동 생성
@AllArgsConstructor
// 매개변수가 없는 생성자를 자동 생성
@NoArgsConstructor
public class TodoVO {
	private Long tno;
	private String title;
	private LocalDate dueDate;
	private boolean finished;
}

 

테스트용 페이지도 하나 만들어보자.

TodoDAOTests

package org.bigdata.controller;

import java.time.LocalDate;

import org.junit.Before;
import org.junit.Test;

import todo.dao.TodoDAO;
import todo.domain.TodoVO;

public class TodoDAOTests {
	private TodoDAO todoDAO;
	
	@Before
	public void ready() {
		todoDAO = new TodoDAO();
	}

	@Test
	public void testInsert() throws Exception {
		TodoVO todoVO = TodoVO.builder()
				.title("sample")
				.dueDate(LocalDate.of(2024, 8, 29))
				.build();
		
		todoDAO.insert(todoVO);
		System.out.println("insert");
	}
}

 

실행을 해보면 로그가 찍히고 데이터가 잘 나오는 것을 볼 수 있다.