본문 바로가기
  • 1+1=3
개발삽질/SSAFY하는 동안 기록

[Backend]JDBC 직접 로딩해보기

by 여스 2022. 3. 22.
반응형

고백하자면,싸피에서 배우기 전까지는 jdbc가 어떻게 돌아가는지 이해하지 못하고 그냥 스프링을 갖다썼다.

항상 원리를 이해하기를 고팠고, 이제 배웠으니 잊지말도록 기록해야겠다.....

 

고 생각했는데 배운지 거의 1주일 지나서 블로그에 기록중ㅋㅋㅋ

 

JDBC란,

Java Database Connectivity를 말한다.

java에서 DB에 접속할 수 있도록 하는 API.

JDBC는 데이터베이스에서 자료를 쿼리하거나 업데이트하는 방법을 제공한다. 패키지는 java.sql와 javax.sql에 있다.

 

JDBC작업순서

1. 드라이버 로딩

2. DB 연결(Connection 생성)

3. SQL 실행준비

  3-1. SQL 작성

  3-2. statement 생성(statement, preparedStatement)

4. SQL 실행

  4-1. insert, update, delete

     이 경우에는 리턴으로 몇개의 행이 영향받았는지 int가 리턴된다.

     *      int x = stmt.execteUpdate(sql);
     *    int x = pstmt.executeUpdate();

  4-2. select

     *      ResultSet rs = pstmt.executeQuery();
     *      rs.next() [단독, if, while]
     *      값얻기 : rs.getString()
     *            rs.getInt() 등등등....

5. DB연결종료: 연결역순으로 종료.

 

드라이버 다운받은 곳: https://dev.mysql.com/downloads/connector/j/

 

MySQL :: Download Connector/J

MySQL Connector/J 8.0 is highly recommended for use with MySQL Server 8.0, 5.7 and 5.6. Please upgrade to MySQL Connector/J 8.0.

dev.mysql.com

 

 

그럼 순서대로 연결해보자!

 

 

드라이버 로딩

구조는 다음과 같다. 이중 디비와 연결하는 핵심부분만 살펴보자.

먼저 Build Path에 외부라이버리로 sql connector.jar가 연결되도록 설정해야 한다! 이.jar파일은 저위에 적은 mysql홈페이지에서 다운받으면 된다.

외부 라이브러리를 추가했으면, 사용할 드라이버의 경로를 명시해줘야 한다. 이 드라이버의 경로(이름)은 com.mysql.cj.jdbc.Driver 이다.

그럼 아래처럼 DBConnection객체를 만들면서 필요한 정보(Driver경로, 내 mysql url(난 포트번호 3307임), 사용할 디비이름과 비번을 넣는다.

글고 Class.forName으로 외부라이브러리(=mysql드라이버)를 로딩해주고(.forName()하면 이게 ㄹㅇ신기한게 자동으로 객체를 생성해주고 DriverManager에 등록까지 해준다ㄷㄷ), 참고: https://pjh3749.tistory.com/250  

위 링크에서 .forName()의 비밀을 파헤쳐보삼.

암튼 그렇게 드라이버객체를 생성해서 DriverManager에 등록해주면, getConnection()함수를 이용해서 Connection객체를 갖다쓸수 있게 된다.

package com.ssafy.jdbctest.util;

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

public class DBConnection {
	private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
	private static final String URL = "jdbc:mysql://127.0.0.1:3307/ssafydb?serverTimezone=UTC&useUniCode=yes&characterEncoding=UTF-8";
	private static final String DB_ID = "디비아이디";
	private static final String DB_PASS = "내비번";
	
	static {
		try {
			Class.forName(DRIVER);
			System.out.println("드라이버 로딩 성공");
		}catch (ClassNotFoundException e) {
			// TODO: handle exception
			e.printStackTrace();
			System.out.println("드라이버 로딩 실패");
		}
	}
	
	public static Connection getConnection() throws SQLException {
		return DriverManager.getConnection(URL, DB_ID, DB_PASS);
	}
}

 

 

DB연결, SQL준비, 실행

이 예제에서는 Dao 인터페이스를 만들고, 이를 implements한 DaoImpl에서 디비연결, 비즈니스로직을 작성하였다.

일단 싱글톤 방식으로 DaoImpl을 생성하도록 하였다.

그리고 더

중요한 부분은 searchAll()함수에서 볼 수 있는데, DBConneciton.getConncection()을 통해 방금 위에서 만든 기능을 이용하여 Connection객체를 가지고 온 것이다. 이 객체에다가 preparedStatement를 넣어주고, executeQuery()를 통해 result를 받아오고, rs.next()를 돌면서 결과를 받아오는 구조이다.

원리를 알고 보면 재밌고 간단하다.(물론 안보고 쓰라하면 못함^^)

package com.ssafy.jdbctest;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.mysql.cj.xdevapi.PreparableStatement;
import com.ssafy.jdbctest.util.DBClose;
import com.ssafy.jdbctest.util.DBConnection;

public class ProductDaoImpl implements ProductDao{
	private static ProductDao productDao;
	
	private ProductDaoImpl() {
		
	}
	
	public static ProductDao getProductDao() {
		if(productDao==null) {
			productDao = new ProductDaoImpl();
		}
		
		return productDao;
	}
	
	
	@Override
	public List<ProductDto> searchAll() {
		List<ProductDto> list = new ArrayList<>();
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DBConnection.getConnection();
			StringBuilder sql = new StringBuilder();
			sql.append("select product_id, product_name, product_price, product_desc, ");
			sql.append( "date_format(register_date, '%y.%m.%d') register_date \n");
			sql.append("from product");
			
			pstmt = conn.prepareStatement(sql.toString());
			rs = pstmt.executeQuery();
			
			while (rs.next()) {
				ProductDto productDto = new ProductDto();
				productDto.setProductId(rs.getString("product_id"));
				productDto.setProductName(rs.getString("product_name"));
				productDto.setProductPrice(rs.getInt("product_price"));
				productDto.setProductDesc(rs.getString("product_desc"));
				productDto.setRegisterDate(rs.getString("register_date"));

				list.add(productDto);
			}
			
			
		}catch (SQLException e) {
			e.printStackTrace();
		}finally {
			DBClose.close(conn,pstmt,rs);
		}
		
		return list;
	}
    
    ...생략

 

 

DB 연결해제

맨 아래처럼 한방에 해도 괜찮다. 핵심은 ResultSet -> PreparedStatement ->Conneciton 순으로 닫아줘야 한다는 것이다.

package com.ssafy.jdbctest.util;

import java.sql.*;

public class DBClose {

	public static void close(Connection conn, PreparedStatement pstmt) {
		try {
			if(pstmt != null)
				pstmt.close();
			if(conn != null)
				conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
		try {
			if(rs != null)
				rs.close();
			if(pstmt != null)
				pstmt.close();
			if(conn != null)
				conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
//	public static void close(AutoCloseable...autoCloseables) {
//		for(AutoCloseable ac : autoCloseables) {
//			if(ac != null) {
//				try {
//					ac.close();
//				} catch (Exception e) {
//					e.printStackTrace();
//				}
//			}
//		}
//	}
	
}
반응형

댓글