[JAVA]_11일차

전희주·2023년 4월 19일
0

JAVA

목록 보기
12/24

✔ JDBC (Java DataBase Connectivity)

  • 1) Java와 DBMS (오라클, MySQL, MaviaDB...) 연동 기술

    • 표준화되어 웹 유무와 상관없이 JDBC 사용 가능 (Web 포함)
    • JDBC API를 사용해서 다양한 벤더(Oracle, MySQL 등)의 데이터베이스와 연동할 수 있다.
  • 2) Java => 접속(by JDBC) => Oracle, ms-SQL...

    • 어떤 데이터 베이스든 ✨ 일관된 방법(interface)으로 연동이 가능하다.
  • 3) 자바와 연동하기 위한 사전 환경
    모든 DB 종류와의 연동 기술을 알아야 한다 ?

    • 불가능
  • 4) ✨(중요) Java 진영에서 인터페이스를 구현

    • ✨ 각 벤더(Oracle, MySQL 등)는 인터페이스를 implements
    • 드라이버 필요 (*.jar 사용하도록 build path 해야 한다) => 컴파일러에게 알려줌
  • JDBC 드라이버(각 벤더에서 생성된 클래스 파일들)는 DB와 통신을 담당하는 인터페이스로, DB와 연결하는 Driver 클래스를 만들 때 반드시 implements 해야 한다.

  • 벤더에서는 해당 벤더에 맞는 JDBC 드라이버를 구현해서 제공하고, 개발자는 이JDBC 드라이버의 구현체를 이용해서 특정 벤더의 DB에 액세스할 수 있다.

    • 이 때문에 드라이버는 어떤 한 DB에 종속적으로 적용되지 않는다.
    • DB를 변경한다면 드라이버만 교체하면 된다.
  • JDBC 드라이버 예) 오라클 드라이버

    • ✨ 경로 기억 C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib

- 위에 3개 다 쓰는게 아니라(충돌 발생) 하나만 사용 

JDBC 연동 과정

1) build path

  • 벤더 별 드라이버build path 방법 (ojdbc6_g.jar)

    • 오라클 드라이버가 있는 곳

2) 4가지 정보 입력

 String driver = "oracle.jdbc.driver.OracleDriver"; 
 String url = "jdbc:oracle:thin:@localhost:1521:xe";
 String id ="SCOTT" 
 String password ="TIGER" 
  • 입력 정보 sql developer 에서 확인

  • 사용자 지정 계정 생성
    id: system
    pw: oracle
  • 자동 계정 생성
    id: SCOTT
    pw: TIGER

3) 드라이버 로딩

  • 오라클 드라이버 클래스를 메모리에 할당 (객체 생성 필)
  • 문자열로 지정된 객체를 메모리에 할당
    • new는 사용하지 못함 (문자열이므로)
    • Class.ForName(" ");
package p01;

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

public class SelectTest {

	public static void main(String[] args) {

		// 입력 순서 아래와 같이 고정 
		 String driver = "oracle.jdbc.driver.OracleDriver"; 
		 String url = "jdbc:oracle:thin:@localhost:1521:xe";
		 String userid ="SCOTT"; 
		 String passwd ="TIGER";  
		 
        // 비-런타임 계열 에러는 컴파일 에러 발생하므로 예외처리가 필수임 cf. 런타임 계열
		// 파일 입출력, sql 연동시 예외처리 구현 필수  
		// 쓰려고하는 상대방의 메소드(forname())가 throws로 예외(ClassNotFoundException)던져줬으니까 (비런타임 계열은 모두 throws 하는데)
		// 이걸 받는 쪽에서 예외처리 안해주면 컴파일 에러 발생 
		// Class.forName(driver);
        
		 try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		 
		 
		 try {
			Connection con = DriverManager.getConnection(url, userid, passwd);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		 
	}

	
}



4) 연결(Connection 맺기)

Connection con = DriverManager.getConnection(url, id, pw);

Connection : 인터페이스

5) SQL 문 작성

 String sql = "select deptno, dname, loc from dept" ;// 반드시 ; 제외 

6) SQL 문을 전송하는 클래스

  • PreparedStatement : 인터페이스에 해당
    • Statement의 하위 인터페이스
    • SQL문을 미리 컴파일하여 실행 속도를 높인다.
PreparedStatement pstmt = con.prepareStatement(sql ); 

pstmt.execute(); //create 문 


// 아래는 ResultSet 값을 리턴
// ResultSet은 SELECT문의 결과를 저장하는 객체ResultSet rs= pstmt.executeQuery(); //select 문 
// 아래는 int 값을 리턴 (실제 쿼리문이적용된 행의 갯수가 반환) int n = pstmt.executeUpdate(); //insert, delete, update 문 

  • ResultSet 구조도
    • next()는 행을 선택해주는 역할
    • while문을 통해 next()가 false 일때까지 반복
while(rs.next()){} 
  • getString(), getInt() 열을 선택해주는 역할 (가져오는 테이블에 저장된 자료형에 따름)
rs = pstmt.executeQuery(); 
while(rs.next()){
	// 한 행씩 반복 처리 
    //"deptno" : 컬럼헤더값
    int deptno = rs.getInt("deptno")
    String name = rs.getString(2);
    String loc = rs.getString("loc"); 

} //end while 
  • 컬럼헤더 값 관련 주의 사항
package p01;

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

public class SelectTest {

	public static void main(String[] args) {

		// 입력 순서 아래와 같이 고정 
		 String driver = "oracle.jdbc.driver.OracleDriver"; 
		 String url = "jdbc:oracle:thin:@localhost:1521:xe";
		 String userid ="SCOTT"; 
		 String passwd ="TIGER";  
		 

		 try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		 
		 
		 try {
			Connection con = DriverManager.getConnection(url, userid, passwd);
		    String sql = "select deptno, dname, loc from dept" ;// 반드시 ; 제외 
			
		    PreparedStatement pstmt = con.prepareStatement(sql); 
		    
		    ResultSet rs= pstmt.executeQuery();
		    
		    while(rs.next()){
		    	// 한 행씩 반복 처리 
		        //"deptno" : 컬럼헤더값
		        int deptno = rs.getInt("deptno"); //테이블 index 1부터 시작 
		        String dname = rs.getString(2);
		        String loc = rs.getString("loc"); 
		        System.out.println(deptno+"\t"+dname+"\t"+loc);

		    }
		    
		    
		 } catch (SQLException e) {
			e.printStackTrace();
		} 
		 
	}

	
}
  • 실행 결과

7) 사용했던 자원 close

  • 사용했던 자원 close (역순으로 진행)
    • 1) ResultSet 객체 close
      • rs.close();
    • 2) Statement 객체 close
      • pstmt.close();
    • 3) Connection 객체 close
      • con.close();

JDBC Flow (insert)

  • 1) build path
    • ojdbc6_g.jar
  • 2) 4가지 정보 입력
  • 3) 드라이버 로딩
  • 4) connect 맺기
  • 5) sql 문 작성
    +) PK 특징:
    • 테이블 당 1개만 존재,
    • 중복 불가 (UINQUE),
    • 값을 반드시 가짐 (IS NOT NULL),
    • 복합 컬럼 가능(여러 키 조합으로 PK키 생성 가능)

      +) SQL에서 NUMBER(2,0)은 숫자형 데이터 타입으로, 최대 2자리의 숫자를 저장할 수 있는 데이터 타입 의미
String sql = "insert into dept(deptno, dname, loc) 
// 1, 2, 3
// 테이블 인덱스는 1부터 시작 (배열과 다름) 
values(?,?,?)"; 

String sql = "select deptno, dname, loc from dept where deptno = ?" ; 
  • 6) PreparedStatement 얻기
PreparedStatement pstmt = con.prepareStatement(sql); 코드를 입력하세요
  • => 있으면 값을 먼저 설정해야 한다

    • pstmt.setInt(위치, 값);

      • pstmt.setInt(1, 50);
    • pstmt.setString(위치, 값);

      • pstmt.setString(2, "개발");

    • int n = pstmt.execute Update();

      • PreparedStatement 객체인 pstmt를 실행하여 INSERT, UPDATE, DELETE(DML)가 데이터베이스에 영향을 미친(row affected) 행의 수를 int 자료형으로 반환하여 n 변수에 할당하는 코드

      +) INSERT, UPDATE, DELETE(DML)은 commit이 필수고, rollback 시 취소

  • java는 auto commit, sql developer는 명시적 commit

insert into dept(deptno, dname, loc) 
values(1, '개발', '서울'); 
commit; 
  • 7) close
    • pstmt.close();
    • con.close();

JDBC Flow (update)

  • 1) build path
    • ojdbc6_g.jar
  • 2) 4가지 정보 입력
  • 3) 드라이버 로딩
  • 4) connect 맺기
  • 5) sql 문 작성
String sql = " update dept "	// 반드시 ; 제외
					 + " set dname=?, loc=? "
					 + " where deptno=? ";	
  • 6) PreparedStatement 얻기
PreparedStatement pstmt = con.prepareStatement(sql); 코드를 입력하세요
  • => 있으면 값을 먼저 설정해야 한다
    • pstmt.setInt(위치, 값);
      • pstmt.setInt(1, 50);
    • pstmt.setString(위치, 값);
      • pstmt.setString(2, "개발");

    • int n = pstmt.execute Update();
      • PreparedStatement 객체인 pstmt를 실행하여 INSERT, UPDATE, DELETE(DML)가 데이터베이스에 영향을 미친(row affected) 행의 수를 int 자료형으로 반환하여 n 변수에 할당하는 코드
+) INSERT, UPDATE, DELETE(DML)은 commit이 필수고, rollback 시 취소 
  • 7) close
    • pstmt.close();
    • con.close();

+) DML 정상 작동 (유의 사항)

  • DML => 이클립스에서 (자동 commit)컴파일 후 sql developer 실행하거나,
  • sql developer에서 먼저 명시적으로 commit 해주거나,

JDBC Flow (delete)

  • 1) build path
    • ojdbc6_g.jar
  • 2) 4가지 정보 입력
  • 3) 드라이버 로딩
  • 4) connect 맺기
  • 5) sql 문 작성
String sql = " delete from dept where deptno=? ";
  • 6) PreparedStatement 얻기
PreparedStatement pstmt = con.prepareStatement(sql); 코드를 입력하세요
  • => 있으면 값을 먼저 설정해야 한다

    • pstmt.setInt(위치, 값);

      • pstmt.setInt(1, 50);
    • pstmt.setString(위치, 값);

      • pstmt.setString(2, "개발");

    • int n = pstmt.execute Update();

      • PreparedStatement 객체인 pstmt를 실행하여 INSERT, UPDATE, DELETE(DML)가 데이터베이스에 영향을 미친(row affected) 행의 수를 int 자료형으로 반환하여 n 변수에 할당하는 코드

      +) INSERT, UPDATE, DELETE(DML)은 commit이 필수고, rollback 시 취소

  • 7) close

    • pstmt.close();
    • con.close();

+) DML 정상 작동 (유의 사항)

  • DML => 이클립스에서 (자동 commit)컴파일 후 sql developer 실행하거나,
  • sql developer에서 먼저 명시적으로 commit 해주거나,

트랜잭션 (transaction)

  • 트랜잭션

  • 여러 DML (여러 작업)을 하나의 작업으로 처리하도록 묶음

    • 예) 계좌이체 - 작업개수
      A (1000) B => A (500) B (500)
      update insert
  • 여러 DML(여러 작업)을 하나의 작업으로 처리하도록 묶음

  • [1], [2]번까지 잘 실행되다가 [3]번 작업 시 소프트웨어가 중단되거나 하드웨어가 고장이 발생하여 작업에 오류가 생긴다면?

  • [2]번까지의 모든 작업을 취소하고 트랜잭션 작업 전인 데이터베이스 초기 상태로 돌아가게 된다.

  • Java에서 트랜잭션 사용하기
    • Connection 클래스를 통해 연결하고자 하는 데이터베이스와 연결할 수 있습니다.
    • 이 커넥션은 별다른 설정을 하지 않으면 default로 autocommit이기 때문에 커넥션에서 실행한 모든 쿼리문은 독립적으로 커밋하게 됩니다.
    • 별도의 논리적 단위로 트랜잭션을 묶고 싶다면 위 코드처럼 작성해주면 개발자가 트랜잭션의 범위를 정할 수 있습니다.
public void query(String sql) {
	try (Connection connection){
		connection.setAutoCommit(false); // 설정하지 않으면 true이다. (비활성화) 
		...// 비즈니스 로직
         del member(); 
		  // 비즈니스 로직에 에러가 발생하지 않으면 Commit
         connection.commit();
         
         
	} catch (SQLException e){
		connection.rollback(); // 에러가 발생하면 rollback
	} finally {
		connection.setAutoCommit(true);
	}
}

✨ (중요) DTO 패턴

APPENDIX

✨ JDBC API Flow

    1. JDBC 드라이버 로딩
    • 사용하고자 하는 JDBC 드라이버를 로딩한다. JDBC 드라이버는 DriverManager 클래스를 통해서 로딩된다.
Class.forName("com.jdbc.cj.mysql.Driver");
    1. Connection 객체 생성
    • Connection은 특정 DB와의 연결정보를 가지는 인터페이스이다.
    • JDBC 드라이버가 정상적으로 로딩되면 DriverManager가 Connection 객체를 가져온다.
// 연결 정보
String url = "jdbc:mysql://localhost:3306/mydb";
String username = "root";
String password = "";
// 정보 등록 -> 커넥션 얻기
Connection connect = DriverManager.getConnection(url, username, password);
    1. Statement 객체 생성
    • Statement는 작성된 SQL 쿼리문을 DB에 전송하는 방법을 정의한 인터페이스이다.
  • PreparedStatement
    • Statement의 하위 인터페이스
    • SQL문을 미리 컴파일하여 실행 속도를 높인다.
  • CallableStatement
    • PreparedStatement의 하위 인터페이스
    • DBMS의 Stored procedure을 호출한다.
Statement state = connect.createStatement();
    1. Query 실행
    • Statement 객체의 executeQuery(), executeUpdate() 메서드로 SQL 쿼리를 실행할 수 있다. 파라미터로 쿼리 문장을 담은 String을 전달한다.
  • executeQuery()

    • SELECT
    • return type : ResultSet
  • executeUpdate()

    • INSERT, UPDATE, DELETE
    • return type : int (변경이 일어난 row index)
ResultSet rs = state.excuteQuery("SELECT * FROM USER");
    1. ResultSet 객체로 데이터 조회
    • ResultSet은 SELECT 구문 실행 결과를 조회할 수 있는 방법을 정의한 인터페이스이다.
    • ResultSet 객체는 쿼리에 의해 생성된 테이블을 담고 있으며 next() 메서드를 통해 테이블의 row를 순회할 수 있다.
    • get___() 메서드로 한 row의 특정 column 값을 가져온다.
while(rs.next()) {
	String name = rs.getString("column명");
    int id = rs.getInt("column명");
}
    1. close()
    • 사용한 객체를 역순으로 닫아준다.
rs.close();
state.close();
connection.close();

0개의 댓글