[스프링] 1. SQL & JDBC 프로그래밍 - JDBC

JM·2022년 10월 19일
0
post-thumbnail

JDBC

참고링크 : https://debugdaldal.tistory.com/181

JDBC의 정의

  • 자바를 이용한 데이터베이스 접속과 SQL 문장의 실행, 그리고 실행 결과로 얻어진 데이터의 핸들링을 제공하는 방법과 절차에 관한 규약
  • 자바 프로그램내에서 SQL문을 실행하기 위한 자바 API
  • SQL과 프로그래밍 언어의 통합 접근 중 한 형태
  • 매번 SQL문을 입력하여 실행할 수 없기 떄문에 이를 프로그래밍화 한 것이다.
  • JAVA는 표준 인터페이스인 JDBC API를 제공한다. 또한 데이터베이스 벤더, 또는 써드파티에서는 JDBC 인터페이스를 구현한 드라이버를 제공한다.
  • 벤더란? 판매인 또는 판매업자를 가리키는 말. 예를 들어 컴퓨터의 하드웨어나 소프트웨어 제품이 판매되는 경우, 해당 제품에 대해 책임을 지는 기업을 말한다.

필요한 환경 구성

  • JDK 설치
  • JDBC 드라이버 설치 : pom.xml의 dependencies에 추가
<dependency>   
  <groupId>mysql</groupId>   
       <artifactId>mysql-connector-java</artifactId>
       <version>5.1.45</version>
 </dependency>

JDBC 사용 - 단계별 정리

  1. import java.sql.*;
  2. 드라이버를 로드한다.(각각의 DB벤더가 정한 절차를 따른다.)
  3. Connection 객체를 생성한다.(DB접속)
  4. Statement 객체 생성 및 질의 수행
  5. SQL문에 결과물이 있다면 ResultSet 객체를 생성한다.
  6. 모든 객체를 닫는다.
    (항상 연결하는게 있으면 닫아야 한다. DB는 접속할 수 있는 클라이언트가 무한대가 아니기 때문이다.)

JDBC 클래스의 생성관계

DriverManager를 통해 Connection객체 생성 -> Connection객체를 통해 Statement객체 생성 -> Statement객체를 통해 ResultSet객체 생성
닫을 때는 역순이다.
ResultSet객체 해제 -> Statement객체 해제 -> Connection객체 해제


단계별 설명1

  • IMPORT
    import java.sql.*
  • 드라이버 로드
    Class.forName("com.mysql.jdbc.Driver");

    DB벤더에서 제공하는 객체이다. Class클래스의 forName메소드를 이용하면 해당 객체가

    메모리에 올라간다. new를 통한 객체 생성과 비슷한 동작을 한다. 어떤 벤더사의 DB를 사용하냐에

    따라서 forName()의 인자값은 달라진다.
  • Connection 얻기
    • String dburl = "jdbc:mysql://localhost/dbName";
    • Connection con = DriverManager.getConnection(dburl,ID,PWD);

단계별 설명2

  • Statement 생성
    Statement stmt = con.createStatement();
  • 질의 수행
    ResultSet rs = stmt.executeQuery("select no from user");

    어떤 쿼리를 이용하는지에 따라 실행명령어는 달라진다.
    • any SQL : execute()
    • SELECT : executeQuery()
    • INSERT, UPDATE, DELETE : executeUpdate()

단계별 설명3

  • ResultSet으로 결과 받기

    ResultSet rs = stmt.executeQuery("select no from user");
    while(rs.next())
      System.out.println(rs.getInt("no"));

    ResultSet객체인 rs에 저장되는 것은 쿼리 수행 결과값이 아니다. 결과값은 DB가 가지고 있고, ResultSet객체에 저장되는 것은 해당 결과를 가리키는 레퍼런스이다. 왜냐하면 쿼리결과가 10,000건이 넘는 경우, 이를 서버에 바로 전달하면 서버에 무리가 가기 때문에, 서버에서 필요한 값을 꺼내오는 형식으로 진행된다. 이떄 사용하는 메소드가 next()이다. next()는 처음에 쿼리 결과의 첫번째 레코드를 가리키며, 실행 이후에는 다음 레코드를 가리키게 된다.

  • Close

    • rs.close();
    • stmt.close();
    • con.close();
  • 전체 소스코드

import java.sql.*;


public class Main {

	public static void main(String[] args) throws Exception {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			conn = getConnection();
			stmt = conn.createStatement();
			rs = stmt.executeQuery("select id from guestbook;");
			while(rs.next()) System.out.println(rs.getInt("id"));
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(rs != null) {
				rs.close();
			}
			if(stmt != null) {
				stmt.close();
			}
			if(conn != null) {
				conn.close();
			}
		}
	}
	
	public static Connection getConnection() throws Exception{
		Class.forName("com.mysql.jdbc.Driver");
		
		String dburl = "jdbc:mysql://localhost:3306/connectdb?useSSL=false";
		String ID = "root";
		String PWD = "1111";
		
		Connection conn = DriverManager.getConnection(dburl,ID,PWD);
		return conn;
	}	
}



의문점

public class Main {

	public static void main(String[] args) {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			
			String dburl = "jdbc:mysql://localhost:3306/connectdb?useSSL=false";
			String ID = "root";
			String PWD = "1111";
			
			Connection conn = DriverManager.getConnection(dburl,ID,PWD);
			System.out.println(conn.getClass());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

위 코드에서 Class.forName 의 역할은 무엇일까? 객체를 넘겨받지도 않기 때문에, 왜 필요한 코드인지 의문이 갔다.

Class.forName

위 메소드는 static 메소드이다. 메소드를 호출하면, 먼저 클래스로더가 해당 클래스의 클래스파일을 찾는다. 발견되면 클래스파일을 보고 Class<?> 의 인스턴스(특정 클래스의 메타 데이터)를 생성하여 JVM의 Method Area(Static Area)에 업로드 하게 된다. 만약 Method Area 영역에 메타 데이터가 존재한다면 추가로 Class<?> 의 인스턴스 생성하지 않을 것이다.

jdbc Driver를 사용하려면 해당 드라이버가 JVM에 로드되어 있어야 한다. 자바는 lazy loading을 지원하므로 jdbc Driver가 JVM에 로드되있지 않을 수 있다. 이를 대비하여 명시적으로 드라이버를 로드하는 것이다.

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    /**
     * Construct a new driver and register it with DriverManager
     * 
     * @throws SQLException
     *             if a database error occurs.
     */
    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}

위 코드는 com.mysql.Driver 클래스의 코드이다. 위 클래스가 로드되면 static블럭이 실행되고 java.sql.DriverManager에 해당 클래스의 인스턴스가 등록된다.

Class.forName("com.mysql.jdbc.Driver");
String dburl = "jdbc:mysql://localhost:3306/connectdb?useSSL=false";
String ID = "root";
String PWD = "1111";
Connection conn = DriverManager.getConnection(dburl,ID,PWD);

이 때문에, DriverManager에서 connection을 가져올 수 있는 것이다.


생각해보기

  • java.sql 외에 JAVA가 인터페이스만 대부분 제공하는 패키지는 또 어떤 것이 있을까요?
    JAVA가 인터페이스만 제공하는 패키지는 자바 ORM 명세인 JPA가 있다.
    자바ORM이란? 객체와 DB의 테이블 매핑을 이루는 것. SQL문 작성없이 DB데이터를 JAVA객체로 받을 수 있다.
    JPA란? 자바 ORM기술에 대한 API표준 명세.
profile
나는 사는데로 생각하지 않고, 생각하는데로 살겠다

0개의 댓글