JAVA - Java.sql : JDBC ( DB Connection 연결 )

TopOfTheHead·2026년 4월 15일

자바 ( JAVA )

목록 보기
24/28

JDBC ( Java Database Connector ) :
자바 어플리케이션에서 DB와 통신할 수 있도록 연결하는 API 역할의 인터페이스
Java 어플리케이션에서 DB에 접근하여 사용자가 작성한 SQL을 통해 SELECT , INSERT , UPDATE , DELETE 수행.

JDBC인덱스0이 아닌, 1부터 시작

인터페이스를 정의하고 의존성 역전을 통해 다형성을 이용하여 다양한 DBMS에 대한 구현체드라이버로서 각각 구현
어플리케이션소스코드를 수정하지 않아도 쉽게 DBMS를 교체 가능

DB Client( = Datagrip 등 )은 JDBC를 이용하여 DB와 통신을 수행

。각 DBMS에 대한 JDBC 구현체드라이버라고 한다.

JDBC 기능 사용 시 커서 기능을 사용하는 자원을 모두 해제해야한다.

ResultSet, ConnectionPool, PreparedStatement, Statement, Connection

DB 커서를 사용하는 클래스들로서 자원소모가 매우 크므로, 클래스객체 생성 시 객체.close()를 통해 반드시 닫아야한다.
언어에서 자동으로 닫는게 지원하더라도 명시적으로 작성하는게 좋다.

Connection -> PreparedStatement -> ResultSet 순으로 생성 시 작업 후 반드시 역순으로 자원 해제

		try (Connection conn = ConnectionUtil
			.ConnectionDriver
			.getConnection(
				ConnectionUtil
					.DatabaseType.MySql
			)
		){
			Statement stmt = conn.createStatement();
			// SQL 문을 실행
			stmt.execute(memberTableDdl);
			stmt.execute(productTableDdl);
//
			// Statement 를 반드시 닫아야한다.
			stmt.close();
		} catch ( Exception e ){
			e.printStackTrace();
		}

Statement객체 -> Connection 객체 순으로 종료
Connection객체try ~ with문에 의해 종료

java.sql
Java에서 DB와 연결하고 SQL을 실행하기 위한 JAVA API(= JDBC)를 제공하는 표준 패키지
DB Connection / SQL 실행 등의 기능을 제공

Connection / DriverManager / Statement / PreparedStatement / ResultSet 등이 존재

Connection : java.sql.Connection
DAO 역할을 수행하는 DB 연결객체

DriverManager.getConnection()에 의해 즉석에서 생성되어 제공되거나, Coonection Pool에서 유휴 상태로 저장 및 제공됨

  • Connection객체.setAutoCommit( Boolean )
    。연결된 DBMSAuto Commit 기능을 종료(false) / 시작(true)하는 메서드
    트랜잭션이 종료 된 경우 다른 사용자를 위해 AutoCommit 기능을 재시작하여 기본값으로 설정

DriverManager
TCP 연결을 통한 DB Connection 객체 생성 시 사용되는 클래스
DriverManager.getConnection(DB URL, DB계정명, DB비밀번호) : Connection 객체를 생성하는 메서드

DB Connection을 즉석에서 생성 시 TCP 3-way Transaction에 의해 연결되어 생성되므로 시간이 많이 소요
Connection Pool을 통해 사전에 DB Connection을 생성 및 유휴 상태로 준비하여 제공하는 방식을 많이 사용.

DriverManager.getConnection(
     "jdbc:mysql://localhost:3306/,
     "wjdtn747",
     "wjd747"
);

Statement / PreparedStatement

PreparedStatement pstmt = conn.prepareStatement("SQL문"); 

Connection객체를 활용하여 SQL을 실행하는 DAO 객체
StatementPreparedStatement의 차이는 SQL Injection 방지 용도의 컴파일 수행 여부 차이

。 초기 Statement가 등장했으나, SQL Injection으로 인한 보안위협을 방지하고자 PreparedStatement가 도출
PreparedStatement 사용 시 SQL문과 입력되는 매개변수를 분리하여 DBMS에게 전달함으로서 SQL 인젝션을 방지

  • PreparedStatement을 사용하는 이유?
    。기존 Statement의 경우 DBMS 전달 시, JAVA에서 SQL문매개변수포매팅함으로써 하나의 SQL구문으로 완성되어 전달되면서 SQL Injection검증하지 못하는 단점이 존재.

    SQL문과 반영될 매개변수를 각각 DBMS에 분리해서 전달함으로써 SQL Injection을 방지
    Binding Parameter = Placeholder( ? )로서 비워둔 상태로 정의한 SQL문을 통해 PreparedStatement객체 생성 후 , 이후 pstmt.setString()을 통해서 매개변수를 정의하면서 바인딩을 수행

    。실제로 select * from 테이블 where id = ?SQLDBMS에서 실행 시 매개변수를 입력하라고 도출

PreparedStatement메서드
WRITE 시 사용 : pstmt객체.execute(), pstmt객체.executeUpdate()
READ 시 사용 : pstmt객체.executeQuery()
매개변수 삽입 : pstmt객체.setString()

  • pstmt.setString(인덱스, "매개변수")
    PreparedStatement 객체 생성자로 전달한 SQL문?바인딩매개변수를 정의
	PreparedStatement pstmt = connection.prepareStatement(
				"""
				SELECT *
				FROM `members`
				WHERE email = ? 
				AND password = ?;	
			"""
			);
			pstmt.setString(1,"wjdtn747@naver.com");
			pstmt.setString(2,"123");
  • pstmt.executeQuery() :
    preparedStatement 객체SQL문 : SELECT를 통한 조회 결과ResultSet객체로 반환
ResultSet foundedResultsSet = pstmt.executeQuery();
  • pstmt.execute()
    DDL / DML 등의 SQL 실행 시 사용하는 가장 범용적인 SQL문 실행 메서드
    ▶ 결과가 ResultSet이면 true, 아닌 경우 false로 반환
 boolean executeResult = pstmt.execute(); // boolean 반환 성공 & 실패 여부
			if (!executeResult) {
				int affectedRowCounter = stmt.getUpdateCount();
				System.out.println("affected : " + affectedRowCounter);
			}
  • pstmt.executeUpate()
    INSERT / UPDATE / DELETE 등의 DML 수행 시 사용하는 SQL문 실행 메서드
    ▶ 영향 받은 행의 수int로서 반환
int affectedRowCount = pstmt.executeUpdate();

ResultSet
PreparedStatement를 통해 DB에서 조회결과를 저장하는 객체
DB 서버와 연결된 상태에서 조회 데이터를 한 Record 씩 읽어오는 커서 기반 인터페이스

PreparedStatement객체.executeQuery(); 을 통해 생성

ResultSet객체.close()를 수행 시 해당 ResultSet객체에 대한 Connection이 종료되었으므로 다시 조회가 불가능.

ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
    System.out.println(rs.getString("name"));
}

ResultSet객체getter 메서드필드명 / 인덱스를 통해 조회된 데이터를 확인할 수 있음.

  • RS객체.next()
    조회결과를 포함하는 ResultSet 객체에서 커서를 통해 다음 데이터 행 존재 여부를 검사 후 Boolean을 반환

    단건조회 : if(RS객체.next())
    다건조회 : while(RS객체.next())
    데이터 행 순회 시 사용

  • RS객체.get메서드("컬럼명")
    ResultSet 객체에서 컬럼명에 해당하는 데이터를 반환하는 메서드

    ResultSet 객체에서 데이터를 조회 시 Object Type으로 가져오는 특징이 존재
    getInt() / getString() / getLong() / ... 등의 Data Type메서드를 활용하여 Type Casting을 수행
 while(resultSet.next()){
				// 컬럼명으로 해당 행의 데이터 조회
				long id = resultSet.getLong("id");
				String name = resultSet.getString("name");
				int price = resultSet.getInt("price");
				int stock = resultSet.getInt("stock");
				System.out.println("%d / %s / %d / %d".formatted(id,name,price,stock));
			}
			resultSet.close();

JDBC를 통해 MySQLDB Connection 객체 생성하기

  • SQL을 통해 DBMS 초기화
# DB 생성
DROP DATABASE IF EXISTS jdbc_shop;
CREATE DATABASE jdbc_shop;
# 유저생성
drop user if exists `kf16`;
CREATE USER `kf16`@`%`
IDENTIFIED BY 'wjd747';
# 권한부여
GRANT
    ALL PRIVILEGES
ON
    *.*
TO
    `kf16`@`%`;
FLUSH PRIVILEGES;
  • MySQL 의존성 정의
    MavenRepository에서 주소를 확인 후 build.gradle의존성 정의
implementation 'com.mysql:mysql-connector-j:9.6.0'
  • JAVA에서 MySQLDB Connection 정의
    jdbc:mysql://localhost:3306/jdbc_shop : MySQL DBDB : jdbc_shop 정의

    try ~ with문을 통해 Connection 객체 자동 자원해제하도록 설정
    ▶ 추가적으로 Connection.close()를 정의할 필요가 없음.
		final String PORT = "3306";
		final String URL =  "jdbc:mysql://localhost:%s/jdbc_shop".formatted(PORT); // MySQL 내부 jdbc_shop DB에 연결
		final String USER = "kf16";
		final String PASSWORD = "wjd747";
		try(
			Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
			){
			System.out.printf("Drivername %s", connection.getMetaData().getDriverName());
			System.out.println();
			System.out.printf("used url", connection.getMetaData().getURL());
		}catch(Exception e){
			System.out.println("DB Connection Failed");
		}
  • DB Connection 객체의 생성 용도의 Util 클래스 정의
    。다양한 DBMS추상화 함으로써 코드 수정 없이 DB 교체가 가능하도록 설계

    abstract class를 통해 객체 생성 차단.
    인터페이스로 대체 가능

    H2 DB, MySQL에 대해서 Connection 생성 시 필요한 파라미터( = URL, USER, PASSWORD )를 Enum을 통해 상수로 관리

    정적 중첩 클래스를 통해 입력된 Enum Type에 따른 DBMS에 해당하는 Connection 객체를 반환
    Boiler plate Code 최소화
public abstract class ConnectionUtil {
	public enum DatabaseType {
		H2("jdbc:h2:mem:test_db", "sa", ""),
		MySql("jdbc:mysql://localhost:3306/jdbc_shop", "kf16", "wjd747");
		private final String URL;
		private final String USER;
		private final String PASSWORD;
		DatabaseType(String URL, String USER, String PASSWORD) {
			this.URL = URL;
			this.USER = USER;
			this.PASSWORD = PASSWORD;
		}
	}
	public static abstract class ConnectionDriver{
		public static Connection getConnection(DatabaseType databaseType) throws SQLException {
			try {
				return DriverManager.getConnection(
					databaseType.URL,
					databaseType.USER,
					databaseType.PASSWORD);
			}catch(Exception e){
				throw new RuntimeException(e);
			}
		}
	}
}
		try (Connection mysqlConnection = ConnectionUtil
			.ConnectionDriver
			.getConnection(
			ConnectionUtil.DatabaseType.MySql
				)
		){
			System.out.printf("Drivername %s", mysqlConnection.getMetaData().getDriverName());
		} catch (Exception e){
			throw new RuntimeException(e);
		}

▶ 다음처럼 try ~ with 문을 통해 필요한 DBMSEnum을 전달하여 알맞은 DB Connection을 반환받을 수 있음.

     
profile
공부기록 블로그

0개의 댓글