ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 5. JDBC가 뭐고 어떻게 사용하나요?
    PROGRAMMING/SQL 2022. 4. 22. 00:15

    하루입니다. 오늘은 JDBC에 대해 알아보고 복습하는 시간을 가지겠습니다.

     


     

    JDBC란?

    • Java DataBase Connectivity의 줄임말이다.
    • 자바가 데이터베이스에 접속해서 SQL을 실행할 수 있도록 하는 표준이다.
    • java.sql 패키지와 javax.sql 패키지에 관련 인터페이스와 클래스가 존재한다.

     

     

     

    JDBC의 주요 API

    API란 어플리케이션 개발에 필요한 기능들이다. 자바가 기본으로 제공하는 것들도 있다. 여기에 나온 건 다 자바에서 제공하는 기능들인 듯. 

     

     

    클래스
      DriverManager

    • JDCB 표준을 구현한 JDBC드라이버를 관리하는 클래스다.
    • Driver를 이용해서 데이터베이스와 연결을 유지하는 Connection객체를 생성한다.
    • Connection getConnection(String url, String username, String password)
      url이 가르키는 데이터베이스에 지정된 계정정보로 연결을 시도한 후 연결을 담당하는 Connection객체를 반환한다.

     


    인터페이스

      Driver

    • JDBC기술을 기반으로 데이터베이스와 연결을 처리하는 Driver를 드라이버레지스트리에 등록한다.
    • DriverManager는 드라이버레지스트리에 등록된 Driver를 이용해서 데이터베이스와 연결을 유지하는 Connection객체를 생성한다.
    • Driver인터페이스를 구현하는 구현 클래스는 DBMS 제작사가 제공한다.

     

    Connection

    • 데이터베이스와 연결을 유지하는 객체다.
    • DriverManager가 Driver를 이용해서 생성한다
    • Connection은 SQL구문을 데이터베이스로 전송하고 실행시키는 Statement, PreparedStatement, CallableStatement 객체를 제공한다.
    • Connection인터페이스를 구현하는 구현 클래스는 DBMS 제작사가 제공한다.
    • void commit( ) : SQL 실행결과를 DB에 반영시킨다.
    • void rollback( ) : SQL 실행결과의 DB 반영을 취소시킨다.
    • void close( ) : DB와의 연결을 해제한다.

     

    Statement, PreparedStatement, CallableStatement

    • SQL구문을 데이터베이스로 전송하고 실행시키는 객체다.
    • Statement, PreparedStatement, CallableStatement인터페이스를 구현하는 구현 클래스는 DBMS 제작사가 제공한다.
    • Statement는 보안상 취약점이 있어서 쓰지 않을 거고, CallableStatement는 프로시저 관련해 사용한다. 우리는 PreparedStatement를 사용할 것이다.

     

    PreparedStatement 인터페이스

    • SQL의 전송을 담당하는 객체다.
    • int executeUpdate()
      INSERT, UPDATE, DELETE 쿼리를 DB로 전송하고, 실행결과를 반환한다.
    • ResultSet executeQuery()
      SELECT 쿼리를 DB로 전송하고, 조회결과를 반환한다.
    • void setXXX(int index, XXX value)
      ?위치에 실제값(파라미터값)을 설정한다.

                     void setString(int index, String value)

                     void setInt(int index, int value)
                     void setLong(int index, long value)
                     void setDouble(int index, double value)
                     void setDate(int index, Date value)

    참고로 쿼리란 데이터베이스에 정보를 요청하는 것이이다. SQL은 Structured Query Language의 약자인데 구조화된 + 질의 + 언어. 오 ... 딱 맞는다.


    ResultSet

    • SQL구문(SELECT) 실행결과를 포함하고 있는 객체다.
    • ResultSet 인터페이스를 구현하는 구현클래스는 DBMS 제작사가 제공한다.
    • boolean next( )
      커서를 다음행으로 이동시킨다. 데이터행이 존재하면 true를 반환한다.
    • XXX getXXX(String columnName) : 컬럼명에 해당하는 값을 반환한다.
      int getInt(String columnName); 와 같은 형태로 사용한다.

     

    ResultSetMetaData

    • SQL구문(SELECT) 실행결과에 대한 부가적인 정보를 포함하고 있는 객체다.
    • ResultSetMetaData 인터페이스를 구현하는 구현클래스는 DBMS제작사가 제공한다.

     


    예외

    SQLException

    • 데이터베이스 엑세스 작업중 오류가 발생하면 이 예외를 던진다.
    • 데이터베이스 오류코드와 오류메세지를 출력한다.

     

    특이한 점. 왜 driver와 connection은 DBMS사가 제공할까? 혹시 사용법이 다른 건 아닐까?

     

    정답은 아니다이다. 자바에서는 driver와 connection이라는 인터페이스를 제공하고 있다. DBMS사들은 이 인터페이스를 이용해 - 인터페이스는 메소드 재정의 등을 통해 사용법은 같아도 구현은 다르게 할 수 있으므로 - 사용법은 같되 내용은 다르게 알아서 각자의 사용법을 구현하는 것이다. 

     

     


     

     

    데이터베이스 엑세스 작업 순서

    JDBC API를 사용해서 자바와 데이터베이스 연동하기

    미리 간단히 보는 연동 순서. 

     DB와 연결해 주는 DRIVER를 가장 먼저 생성한다. 그 다음 DRIVERMANAGER 사용해 CONNECTION 객체를 얻는다. PreparedStatement를 사용해 SQL을 DB로 전송 실행한다. 성공한다면 DB에 데이터가 정상적으로 들어가고, 실패하면 ... 오류의 향연이다.

     

     원래 무언가 다운받아야 한다고 하나 우리는 오라클을 다운받았고 그 안에 오라클 드라이버가 있다고 함. 이 친구가 우리에게 커넥션을 가져다 줄 거야. 

     

     

    1. SQL구문 작성하기

    • SQL 키워드(insert, into, values, select, from, where, order by, asc, desc, in, like, update, set, delete 등)와 테이블명, 시퀀스명, 내장함수명, 컬럼명 자리에는 ? 를 사용할 수 없다. 저 자리엔 값만 올 수 있다고 이해함. 
    • ? 는 값이 위치하는 곳에서만 사용할 수 있다.
    String sql = "insert into sample_products(product_no, product_name, product_company, product_price, product_stock) "
               + "values (products_seq.nextval, ?, ?, ?, ?)";
    • 따옴표 전에는 항상 한 칸을 띄워주자. 그렇지 않으면 밑과 같은 형태로 나온다.
    • product_price from ~ 이렇게 나와야 하는데 product_pricefrom 이런 형태로 나와서 오류가 생긴다.

     

     

     

     

    2. Driver를 드라이버레지스트리에 등록하기 (JDBC 드라이브 JVM 메모리에 로딩하기)

    • Class.forName("패키지경로를 포함하는 클래스이름") 정적메소드는 지정된 클래스를 메모리의 설계도 영역으로 로딩시킨다.
    • oracle.jdbc패키지의 OracleDriver.class 클래스를 메모리로 로딩시키는 수행문이다.
    • OracleDriver는 Driver인터페이스의 구현클래스다.
    • OracleDriver는 메모리에 로딩이 완료되면 드라이버레지스트리에 "jdbc:oracle:thin"이라는 이름으로 OracleDriver를 등록시킨다.
    Class.forName("oracle.jdbc.OracleDriver");

     

     

     

    3. 데이터베이스와 연결을 유지하는 Connection객체 생성(획득)하기

    • Connection DriverManager.getConnection(url, username, password) 정적메소드는 url, username, password 정보와 Driver를 이용해서 데이터베이스와 연결을 유지하는 Connection 인터페이스 구현객체를 반환한다.
    • url에는 드라이버레지스트리에 등록된 Driver이름, DBMS가 실행중인 컴퓨터이름, 포트번호, SID가 포함되어 있다.(오라클 한정)
    • connection참조변수가 참조하는 객체는 Connection 인터페이스를 Oracle에서 구현한 객체다.
    • 다 맞게 입력했다면 connection 객체 획득 가능!
    // url 한 글자라도 잘못 적으면 오류난다. 오타 조심
    Stirng url = "jdbc:oracle:thin:@localhost:1521:xe";
    String username = "haru";
    String password = "asdf1234";
    Connection connection = DriverManager.getConnection(url, username, password);

     

     

     

    4. DDBMS에 SQL 전송과 실행을 담당하는 PreparedStatement객체 획득하기

    • Connection의 PreparedStatement prepareStatement(String sql)메소드는 지정된 SQL을 DBMS로 전송하고 실행시키는 PreparedStatement객체를 반환한다.
    • pstmt가 참조하는 객체는 PreparedStatement 인터페이스를 Oracle에서 구현한 객체다.
    PreparedStatement pstmt = connection.prepareStatement(sql);
    // 앞은 Prepare'd'Statement, 뒤는 prepareStatement다.
    // 차이점은 ... 찾아 봐야 함.

     

     

     

    5. SQL구문의 ?에 값을 바인딩 시키기 (대응시키기)

    pstmt.setString(1, "맥북 프로 13");
    pstmt.setString(2, "애플");
    pstmt.setInt(3, 1960000);
    pstmt.setInt(4, 20);
    // 이렇게 하면 db table에 바로 값 저장된다.
    
    pstmt.setString(1, product.getName);
    pstmt.setString(2, product.getCompany);
    pstmt.setInt(3, product.getPrice);
    pstmt.setInt(4, product.getStock);
    // 이건 값 입력받아 저장하려고 만든 코드

     

     

     

    6. SQL구문을 DBMS로 전송, 실행시키기

    pstmt.executeUpdate();
    
    // 이렇게 하면 몇 개 행 추가됐는지 알 수 있음.
    int updateRowCount = pstmt.executeUpdate();
    System.out.println(updateRowCount + "개 행이 추가되었습니다.");

     

    잠깐만요! 왜 메소드가 갈리나요?

     

    왜냐면 insert update delete는 추가 변경 삭제된 행의 갯수를 반환하잖아요. 그래서 반환타입이 int인 거예요.

    update는 조회결과를 포함하기 때문에 그 결과를 담을 그릇이 필요하고, 그 그릇이 ResultSet이라는 객체랍니다.

     

    아하! 그렇군요!

     

     

     

    7. 실행결과를 사용하기

    • 결과를 출력한다.

     


    8. 리소스 반환

    • 데이터베이스 엑세스 작업이 종료되면 데이터베이스 엑세스 작업으로 점유했던 모든 자원을 반납한다.
    • ResultSet의 close(), PreparedStatement의 close(), Connection의 close() 메소드를 실행한다.
    pstmt.close();
    connection.close();

     

    잠깐만요. 왜 닫아야 하나요? 그냥 열어두면 안 되나요? 왜 닫나요? 왜요? 왜죠?

     

    ^^ ... 굳이 close( )를 하는 이유는 프로세스 때문입니다. 위의 작업을 실행할 때 프로세스가 생기고, 프로세스가 많이 생길수록 오라클 속도는 느려집니다. 갯수 제한이 있어서 어느 순간부터는 더이상 프로세스도 생성할 수 없게 됩니다. 그래서 close( )로 닫아줘야 하는 것입니다.

     

    아하! 그렇군요!

     

    -

     

    순서를 다시 정리하자면 SQL구문 작성 - 드라이버 레지스토리에 등록 - DBMS에 연결해 CONNECTION 객체 얻기 - PREPAREDSTATEMENT객체 획득 - ?에 값 바인딩시키기 - PREPAREDSTATEMNET 사용해 SQL 구문 DBMS로 보내기 - 실행결과 사용하기(출력, 객체에 넣기 등 ... ) - 리소스 반환의 순서로 이루어진다.

     사실 이 과정에서 구문 작성 / 값 바인딩 / 실행결과 사용 말고는 다 같은 과정이다. 그래서 반복되는 축약한 라이브러리가 있으나 지금은 과정에 익숙해지기 위해 쌩으로 할 거다. 프로젝트 들어가면 라이브러리 사용할 것. 

     

     


     

     

    잘못된 정보에 대한 지적은 언제나 환영입니다.

     

    다음 시간은 입력받은 메뉴 번호로 제품 상세 정보, 전체 조회 등을 출력하는 APP을 만들 겁니다. 안녕히 계세요.

Designed by Tistory.