JDBC(Java DataBase Connectivity)

2022. 10. 6. 08:29Dev.Program/Java & Spring

728x90

565~571p

< JDBC(Java DataBase Connectivity) >

회원가입 시스템 프로그램을 콘솔에 출력하는 거!

  • 자바에서 데이터베이스에 접근하기 위한 API

< JDBC 구현 4단계 >

1. 드라이버 로드

  • Class 클래스의 static 메서드 forName() 메서드를 호출하여 DB 연결에 필요한 드라이버 클래스 로드

⇒ ex) MySQL 의 경우 com.mysql.jdbc.Driver 클래스를 지정

단, 미리 해당 드라이버가 포함된 jar 파일이 추가되어 있어야 함

(MySQL : mysql-connector-XXX.jar, Oracle : ojdbcX.jar 등)

  • 드라이버 클래스 위치가 잘못 지정되었거나 클래스 파일이 없을 경우

ClassNotFoundException 예외 발생

  

2. DB 연결

  • DriverManager 클래스의 static 메서드인 getConnection() 메서드를 호출하여 DB 연결(접속)을 수행

⇒ 파라미터로 DB 접속 URL, DB 계정명, DB 패스워드를 전달

⇒ ex) MySQL 의 URL = "jdbc:mysql://DB접속주소:포트번호/DB명"

  • 연결에 성공하면 DB 연결 정보를 담은 Connection 타입 객체가 리턴됨

------------------- 2단계까지는 DB 제품별로 달라지는 부분 -----------------

------------------- 3단계부터는 모든 DB 에 대해 공통적인 부분 -----------------

3. SQL 구문 실행

  • Connection 객체의 prepareStatement() 메서드를 호출하여 파라미터로 SQL 구문을 전달하여 PreparedStatement 객체 연결

⇒ PreparedStatement 타입 객체 리턴됨 

  • PreparedStatement 객체의 executeXXX() 메서드를 호출하여 SQL 구문 실행

⇒ DB 에 조작을 가하는 SQL 문장 실행 시 : executeUpdate()

ex) CREATE, INSERT, UPDATE, DELETE 등

⇒ DB 레코드 조회를 수행하는 SQL 문장 실행 시 : executeQuery()

ex) SELECT

  • PreparedStatement 객체에 전달하는 쿼리문은 외부로부터 전달받은 데이터를 쿼리문에 삽입하기 위해 변수와 문자열 결합을 수행할 수도 있지만 SQL 삽입 공격을 방지하기 위해 데이터 자리를 만능문자(?)로 표시하고 별도의 setXXX() 메서드를 호출하여 데이터를 대체하면서 입력값 검증 수행

⇒ setXXX() 메서드의 XXX 은 전달할 데이터의 자바 데이터타입명

⇒ 파라미터로 만능문자(?)의 순서번호와 전달할 데이터를 전달

ex) 정수형 데이터 idx 변수값을 첫번째 ? 부분에 전달할 경우

pstmt.setInt(1, idx);

4. 결과 처리

  • PreparedStatement 객체의 executeXXX() 메서드를 호출할 경우 메서드 종류에 따라 각각 다른 리턴값이 리턴됨

1) executeUpdate() : int형 데이터 리턴됨. 작업 완료된 레코드 수 리턴

2) executeQuery() : ResultSet 타입 객체 리턴됨. 조회된 레코드 목록 리턴














======== JAVA0413

JDBC 네 단계로 나눌 거

  • 그 전에 필요한 파일 복사해오기

====================================================================

  • 3가지 복사
  • mysql-connector / ojdbc6 / ojdbc8

  • 복사해보기

  • Build Path 기능 추가하기
  • 이렇게 추가됨
  • 지울 땐 이렇게(Remove~)
  • 이건 프로젝트마다 설정해야함

 

> 영구적으로 해야할 때

C:\Program Files\Java\jdk1.8.0_131

  • jdk 폴더로 가기
  • 여기 확인 (혹시나 jdk 가 포함되어있으면 다른 폴더로)
  • C:\Program Files\Java\jre1.8.0_131\lib
  • 우린 jre 폴더 여기로 바로 들어감
  • ext 폴더
  • 사용자가 외부에서 가져오는 라이브러리를 주로 여기에 복사해넣음
  • 우리 mysql-connector-java-5.1.47.jar도 여기로 바로 복사
  • 이제 아무 프로젝트로 들어가도 이게 보인다!
  • 프로그램마다 공통적으로 포함되어있다

====================================================================
























JDBC 를 동작시킬때 필요한 단계

커넥션(2가지_)

======== JDBC_Connect_1.java : 1단계

1단계 ) 드라이버 로드

  • Class 클래스의 static 메서드 forName() 메서드를 호출하여 DB 연결에 필요한 드라이버 클래스 로드

⇒ ex) MySQL 의 경우 com.mysql.jdbc.Driver 클래스를 지정

단, 미리 해당 드라이버가 포함된 jar 파일이 추가되어 있어야 함

(MySQL : mysql-connector-XXX.jar, Oracle : ojdbcX.jar 등)

  • 드라이버 클래스 위치가 잘못 지정되었거나 클래스 파일이 없을 경우

ClassNotFoundException 예외 발생

 

> Class.forName() 메서드를 호출

  • 이 파일 가져다가 클래스 파일로 만들어라- 라는 명령어 = Class.forName

  • try~catch 문 안에 넣기!

 

======== JDBC_Connect_2.java : 2단계

2단계 ) DB 연결

  • DriverManager 클래스의 static 메서드인 getConnection() 메서드를 호출하여 DB 연결(접속)을 수행

⇒ 파라미터로 DB 접속 URL, DB 계정명, DB 패스워드를 전달

⇒ ex) MySQL 의 URL = "jdbc:mysql://DB접속주소:포트번호/DB명"

  • 연결에 성공하면 DB 연결 정보를 담은 Connection 타입 객체가 리턴됨

  • properties (외부에 아이디 비밀번호 만들어두고 갖다 쓰는거→ 한번만 수정하면 되니까)
  • 근데 우린 일단 3번째꺼 사용

  • 이 자리에 localhost, 도메인, IP 등등 다 들어올 수 있다!
  • Mysql 은 포트번호 : 3306, Oracle 포트번호는 1521(근데 Driver가 다름! → 드라이버로드, DB연결 부분만 바꾸면 됨!)
  • 나머지 코드들은 공통으로 사용 가능
  • 디비명 : java
  • 이 중 하나만 틀려도 연결이 안되기 때문에 catch 문 추가해주기
  • 빨간 줄 없어짐!
  • 지금은 디비 없어서 오류
  • 데이터베이스 만들기

 

  • 커넥션 인터페이스 객체가 만들어짐
  • 밖에 만들어줌
  • finally 안에 넣어주기

 

======== JDBC_Connect_3.java : 3단계

3단계 ) PreparedStatement 객체를 Connection 객체와 연결하여 SQL 구문 전달

  • Connection 객체의 prepareStatement() 메서드를 호출하여 파라미터로 SQL 구문을 전달하여 PreparedStatement 객체 연결

⇒ PreparedStatement 타입 객체 리턴됨 

  • PreparedStatement 객체의 executeXXX() 메서드를 호출하여 SQL 구문 실행

⇒ DB 에 조작을 가하는 SQL 문장 실행 시 : executeUpdate()

ex) CREATE, INSERT, UPDATE, DELETE 등

⇒ DB 레코드 조회를 수행하는 SQL 문장 실행 시 : executeQuery()

ex) SELECT

  • PreparedStatement 객체에 전달하는 쿼리문은 외부로부터 전달받은 데이터를 쿼리문에 삽입하기 위해 변수와 문자열 결합을 수행할 수도 있지만 SQL 삽입 공격을 방지하기 위해 데이터 자리를 만능문자(?)로 표시하고 별도의 setXXX() 메서드를 호출하여 데이터를 대체하면서 입력값 검증 수행

⇒ setXXX() 메서드의 XXX 은 전달할 데이터의 자바 데이터타입명

⇒ 파라미터로 만능문자(?)의 순서번호와 전달할 데이터를 전달

ex) 정수형 데이터 idx 변수값을 첫번째 ? 부분에 전달할 경우

pstmt.setInt(1, idx);

  • try ~ catch 문 바깥에 선언

 

  • 실행 후
  • test 테이블 만들어져있다
  • pstmt.executeUpdate();
  • 우리가 원하는 대로 만들어졌는지 조회

 

  • 한 번 더 실행하면
  • 기존에 테이블이 있기 때문에 생성이 안됨(DB 연결 실패!가 아님)
  • catch 문 바꿔주기

 

4단계 ) SQL 구문 실행 및 결과 처리

  • PreparedStatement 객체의 executeXXX() 메서드를 호출할 경우 메서드 종류에 따라 각각 다른 리턴값이 리턴됨

1) executeUpdate() : int형 데이터 리턴됨. 작업 완료된 레코드 수 리턴

2) executeQuery() : ResultSet 타입 객체 리턴됨. 조회된 레코드 목록 리턴

======== JDBC_Connect_4_INSERT.java

  • 내가 한 거

  • 선생님이 하신 거
  • pstmt 는 setXXX 으로 입력받을 형식까지 검사해줌! (맞는 문자만 사용할 수 있게 : int 는 int String은 String 이런식으로)

 

  • 이렇게 적어도 else 문 실행이 아니라 SQL 구문 오류가 뜸
  • else 문 지워준다

 

======== JDBC_Connect_4_UPDATE.java

  • update 는 update 할 게 없으면 리턴값이 0이 된다! 하나도 바뀌지 않았기 때문
  • 그래서 update 문은 else 문 써줘도 됨!

⇒ UPDATE 또는 DELETE 구문의 경우 WHERE 절 사용 시 일치하는 레코드가 없을 경우 수정 또는 삭제가 되지 않아 0 리턴됨

⇒ INSERT 구문의 경우 INSERT 성공 시 1, 실패 시 예외 발생됨

  • 바뀜!
  • 한 번 더 실행하면 이미 10이라는 값이 없기 때문에 update 할 게 없어서
  • update 작업 실패했다고 뜬다!

 

======== JDBC_Connect_4_DELETE.java

  • 이제 전부 삭제 됨
  • 한번 더 실행하면 삭제할 게 없기 때문에 DELETE 작업 실패! 라고 뜸

  • 선생님은 몇개의 레코드가 삭제되었는지 까지 적어줌

 

======== JDBC_Connect_4_SELECT.java

  • 구분 잘 하기! 위에꺼 사용해야함

  • 이 자리에 컬럼명 또는 컬럼 인덱스(int형)를 불러올 수 있다.



create table test2 (idx int primary key auto_increment, name varchar(10));

→ test2 테이블 만들기

 

auto_increment 는 not null이 들어감

 

  • 번호 넣기도 가능

  • 그 이후에 null 넣으면 5부터 시작

 

  • primary key(not null) 지만 auto_increment 때문에 null 가능 (번호 자동 생성)

 

< member 테이블 생성 >

필드
1. 번호(idx) INT형 PK(PRIMARY KEY) AI(AUTO_INCREMENT)
2. 이름(name) VARCHAR(20) NN
3. 나이(age) INT형 NN
4. E-Mail(email) VARCHAR(50) NN UN
5. 주민번호(jumin) VARCHAR(14) NN UN

CREATE TABLE member (
idx INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
age INT NOT NULL,
email VARCHAR(50) NOT NULL UNIQUE,
jumin VARCHAR(14) NOT NULL UNIQUE
);

 

  • 테이블 만들기

 

======== JDBC_Member_Management.java

> 문제

insert() update() delete() select(); 완성하기

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

public class JDBC_Member_Management {

public JDBC_Member_Management() {
// insert();
// update();
// delete();
select();
}

// public void init() {}

public void insert() {
// 외부로부터 전달받은 이름, 나이, E-Mail, 주민번호를 추가
String name = "홍길동";
int age = 20;
String email = "hong@hong.com";
String jumin = "901010-1234567";

String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/java";
String user = "root";
String password = "1234";

Connection con = null;
PreparedStatement pstmt = null;

try {
Class.forName(driver);
System.out.println("드라이버 로드 성공!");

con = DriverManager.getConnection(url, user, password);
System.out.println("DB 연결 성공!");

String sql = "INSERT INTO member(name, age, email, jumin) VALUES(?,?,?,?)";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, name);
pstmt.setInt(2, age);
pstmt.setString(3, email);
pstmt.setString(4, jumin);

int result = pstmt.executeUpdate();

if(result > 0) {
System.out.println("INSERT 작업 성공!");
}

} catch (ClassNotFoundException e) {
System.out.println("드라이버 로드 실패! - " + e.getMessage());
} catch (SQLException e) {
System.out.println("DB 연결 실패! 또는 SQL 구문 오류 발생! - " + e.getMessage());
} finally {
// finally 블록 내에서 DB 관련 자원 반환 필수!
try {
// 생성된 순서의 역순으로 반환
pstmt.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}

}

public void update() {
// 외부로부터 이름, 주민번호를 전달받아 E-Mail 을 변경
String name = "홍길동";
String jumin = "901010-1234567";
String email = "hongildong@hong.com"; // 변경할 E-Mail

String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/java";
String user = "root";
String password = "1234";

Connection con = null;
PreparedStatement pstmt = null;

try {
Class.forName(driver);
System.out.println("드라이버 로드 성공!");

con = DriverManager.getConnection(url, user, password);
System.out.println("DB 연결 성공!");

String sql = "UPDATE member SET email = ? WHERE name = ? && jumin = ?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1, email);
pstmt.setString(2, name);
pstmt.setString(3, jumin);

int result = pstmt.executeUpdate();

if(result > 0) {
System.out.println("UPDATE 작업 성공!");
} else {
System.out.println("UPDATE 작업 실패!");
}

} catch (ClassNotFoundException e) {
System.out.println("드라이버 로드 실패! - " + e.getMessage());
} catch (SQLException e) {
System.out.println("DB 연결 실패! 또는 SQL 구문 오류 발생! - " + e.getMessage());
} finally {
// finally 블록 내에서 DB 관련 자원 반환 필수!
try {
// 생성된 순서의 역순으로 반환
pstmt.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}

}

public void delete() {
// 외부로부터 번호(idx)를 전달받아 삭제
int idx = 4;

String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/java";
String user = "root";
String password = "1234";

Connection con = null;
PreparedStatement pstmt = null;

try {
Class.forName(driver);
System.out.println("드라이버 로드 성공!");

con = DriverManager.getConnection(url, user, password);
System.out.println("DB 연결 성공!");

String sql = "DELETE FROM member WHERE idx = ?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, idx);

int result = pstmt.executeUpdate();

if(result > 0) {
System.out.println("DELETE 작업 성공!");
} else {
System.out.println("DELETE 작업 실패!");
}

} catch (ClassNotFoundException e) {
System.out.println("드라이버 로드 실패! - " + e.getMessage());
} catch (SQLException e) {
System.out.println("DB 연결 실패! 또는 SQL 구문 오류 발생! - " + e.getMessage());
} finally {
// finally 블록 내에서 DB 관련 자원 반환 필수!
try {
// 생성된 순서의 역순으로 반환
pstmt.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}

}

public void select() {
// 모든 레코드를 조회하여 출력
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/java";
String user = "root";
String password = "1234";

Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;

try {
Class.forName(driver);
System.out.println("드라이버 로드 성공!");

con = DriverManager.getConnection(url, user, password);
System.out.println("DB 연결 성공!");

String sql = "SELECT * FROM member";
pstmt = con.prepareStatement(sql);

rs = pstmt.executeQuery();

while(rs.next()) {
int idx = rs.getInt("idx"); // idx 라는 이름의 컬럼명을 가져오기
String name = rs.getString("name");
int age = rs.getInt("age");
String email = rs.getString("email");
String jumin = rs.getString("jumin");
System.out.println(idx + ", " + name + ", " + age + ", " + email + ", " + jumin);
}
} catch (ClassNotFoundException e) {
System.out.println("드라이버 로드 실패! - " + e.getMessage());
} catch (SQLException e) {
System.out.println("DB 연결 실패! 또는 SQL 구문 오류 발생! - " + e.getMessage());
} finally {
// finally 블록 내에서 DB 관련 자원 반환 필수!
try {
// 생성된 순서의 역순으로 반환
rs.close();
pstmt.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
new JDBC_Member_Management();
}

}
  • 내가 푼 문제
  • String sql = "INSERT INTO member VALUES(null,?,?,?,?)";
  • insert 부분 null 은 그냥 추가 가능



  • 따로 떼낼 수 있다!
  • 이제 “SQL 실패”는 따로기 때문에 syso 뒷부분 지워줌



728x90