1. JDBC ; Java DataBase Connectivity
👩🏻💻 자바 / JSP 프로그램 내에서 데이터베이스와 관련된 작업을 처리할 수 있도록 도와주는 자바 표준 인터페이스
👩🏻💻 관계형 데이터베이스 시스템에 접근하여 SQL 문을 실행하기 위한 자바 API 또는 자바 라이브러리
⚡️ JDBC API를 사용하면 DBMS의 종류에 상관없이 데이터베이스 작업을 처리할 수 있다.
➡️ 데이터베이스 관리시스템(DBMS)의 종류 상관없이 동일하게 사용할 수 있는 클래스와 인터페이스로 구성되어 있기 때문
⚡️ JDBC API는 java.sql.* 패키지에 의해 구현되며, 이 패키지는 여러 종류의 데이터베이스에 접근 할 수 있다.
※ java.sql.* 패키지는 단일 API를 제공하는 클래스와 인터페이스의 집합
1) DB 연결
👾 클라이언트 프로그램에서 DB와 연결하려면 해당 DBMS의 JDBC Driver가 필요
📌 연결에 필요한 정보
a. DBMS가 설치된 컴퓨터(서버)의 IP 주소
b. DBMS가 허용하는 포트(Port) 번호
c. 사용자(DB 계정) 및 비밀번호
d. 사용하고자 하는 DB 이름
2) JDBC에 포함되어 있는 클래스와 인터페이스
(1) DriverManager
- JDBC Driver를 관리하며 DB와 연결해서 Connection 구현 객체를 생성
(2) Connection
- Statement, PreparedStatement, CallableStatement 구현 객체를 생성하며 Transaction 처리 및 DB 연결을 끊을 때 사용
(3) Statement
- 주로 변경되지 않는 정적 SQL 문을 실행할 때 사용
(4) PreparedStatement
- 매개변수화된 SQL 문을 사용할 수 있기 때문에 편리성과 보안성이 좋음
- SQL 문을 미리 만들어 두고 변수를 따로 입력하는 방식으로 효율성이나 유지 보수 측면에서 유리
- 기본적으로 Statement 클래스를 상속받기 때문에 Statement 클래스의 모든 메서드를 모두 사용할 수 있음
(5) CallableStatement
- DB에 저장되어 있는 프로시저(procedure)와 함수(function)를 호출할 때 사용
(6) ResultSet
- DB에서 가져온 데이터를 읽을 때 사용
3) JDBC 프로그램 개발 절차
👾 JDBC 뿐만 아니라 오픈소스 라이브러리나 프레임워크 등을 이용해서 프로그램을 작성한다는 것은 해당 라이브러리나 프레임워크의 구조와 성격을 이해하고, 제기하는 규격이나 구조에 맞게 프로그램을 만들어야 함을 의미
📌 1단계 : JDBC 드라이버 로드
· 데이터베이스를 접속하려면 먼저 해당 데이터베이스의 JDBC driver를 로딩
· 이런 과정이 필요한 이유는 JDK에 포함된 JDBC는 실제 구현 내용이 빠진 스펙만 인터페이스로 포함 하기 때문
➡️ 실제로 동작하려면 각 데이터베이스 공급업체에서 구현한 클래스들을 사전에 로딩해야 함
· Class.forName() 메서드를 사용
// MySQL 버전
Class.forName("com.mysql.cj.jdbc.Driver");
⚡️ 이 과정에서 JDBC Driver 클래스의 static 블록이 실행되면서 Driver Manager에 JDBC Driver 객체를 등록하게 된다.
// static 블록
class MysqlDriver {
static {
Driver driver = new MysqlDriver();
DriverManager.registerDriver(driver);
}
}
⚡️ DriverManager에 JDBC Driver가 등록되면 getConnection() 메소드로 DB와 연결할 수 있다.
📌 2단계 : 데이터베이스 연결
· 데이터베이스를 연결하려면 몇 가지 추가 정보가 필요
① JDBC URL
- JDBC URL은 다양한 데이터베이스 정보를 포함
- 각 데이터베이스별로 JDBC URL이 다르므로, 사용하는 데이터 베이스 매뉴얼을 참고하여 작성
jdbc:<서브 프로토콜>:<데이터 원본 식별자>
// MySql의 형식
jdbc:mysql://DB 서버의 IP/스키마(데이터베이스):PORT
ex) jdbc:mysql://localhost:3306/sample
🔎 IP주소 : MySql 데이터베이스가 설치된 컴퓨터의 IP 주소 또는 도메인 이름
🔎 스키마 : 데이터베이스에서 생성된 스키마(데이터베이스) 이름
🔎 PORT : 기본 설정값인 3306 포트를 사용할 때는 생략 가능
② Connection 클래스 인스턴스 래퍼런스 얻기
- DriverManager의 getConnection 메서드를 사용
Connection conn = DriverManager.getConnection(JDBC URL,"아이디", "비밀번호");
🔎 JDBC URL : 해당 데이터베이스에 맞게 미리 정의한 문자열
🔎 아이디와 비밀번호 : 데이터베이스 자체에서 관리하는 계정
➡️ 옆에 사진에 나와 있는 것처럼 보통 아이디는 " root " 비밀번호는 mysql 설치할때 입력한 비밀번호 뜻함
📌 3단계 : Statement 생성
· Statement는 데이터베이스를 연결하여 SQL문을 수행할 수 있도록 하는 클래스
· 대표적으로 아래 메서드를 사용
① executeQuery()
- SELECT 문을 수행할 때 사용
- 반환값은 ResultSet 클래스의 인스턴스로, 해당 SELECT 문의 결과에 해당하는 데이터에 접근할 수 있는 방법을 제공
- 단독으로 사용하기 보다는 ResultSet과 함께 사용할 때가 많다
String sql = "select * from test";
Statement stmt = conn.createStatement();
stmt.executeQuery(sql);
② executeUpdate()
- UPDATE 문, DELETE 문 등을 수행할 때 사용
- 반환값은 int형 데이터로, 처리된 데이터 수를 반환
Statement stmt = conn.createStatement();
stmt.executeUpdate("insert into test values (' " +
getUserName() + " ', ' " + getEmail() + " ') ");
👾 사용자 입력값을 포함해야 할 때는 SQL 문을 변수와 결합해서 만들어야 하므로 코드가 다소 복잡해짐
➡️ 컬럼 수가 많아지면 코드 작성이나 유지보수가 어려움
👾 복잡한 SQL 문을 사용할 때는 Statement의 향상된 기능을 제공하는 PreparedStatement을 사용
③ PreparedStatement
- PreparedStatement는 SQL 문을 미리 만들어 두고 변수를 따로 입력하는 방식
- 기본적으로 Statement 클래스를 상속받기 때문에 Statement 클래스의 메서드를 모두 사용
PreparedStatement pstmt = conn.preparedStatement("insert
into test values(?, ?) ");
pstmt.setString(1, getUserName());
pstmt.setString(2, getEmail());
pstmt.executeUpdate();
🔎 행은 늘어났지만 Statement를 사용할때 보다는 프로그램이 간결해짐
🔎 SQL 문에서 변수가 와야 할 위치에는 물음표만 적어 두고, 물음표자리에는 setXxx() 메서드로 값을 설정
➡️ Xxx에는 String, Int 와 같이 자료형별로 다르게 들어감
④ Statement의 close()
- 다른 JDBC 리소스와 마찬가지로 Statement 역시 사용하지 않을 때는 닫아 주어여 함
- PreparedStatement도 마찬가지
stmt.close();
pstmt.close();
📌 4단계 : SQL 문 전송
· 데이터를 입력, 수정, 삭제하려고 SQL문을 만들때는 PreparedStatement를 사용하여 변수와 적절히 조합하면 됨
➡️ executeUpdate() 메서드를 사용
int count = pstmt.executeUpdate();
💡 이 때 executeUpdate() 메서드는 처리한 로우의 개수를 반환
➡️ 처리된 항목이 없다면 0을 반환
💡 처리 결과는 반환값을 받아서 확인해야 하고, 그럴 필요가없다면 굳이 반환을 받지 않아도 됨
📌 5단계 : 결과받기
· 데이터베이스에서 데이터 결과를 받으려면 Statement나 PreparedStatement의 executeQuery()를 사용
· 입력, 수정, 삭제와 달리 데이터를 가져올 때는 가져온 결과 데이터를 처리하는 ResultSet 객체가 필요
ResultSet rs = pstmt.executeQuery():
💡 ResultSet은 데이터베이스 내부적으로 수행한 SQL 문의 처리 결과를 JDBC에서 쉽게 관리할 수 있게 함
💡 필요한 데이터를 모두 가져온 후 ResultSet을 close()하고나서 connection을 close() 해야 함
💡 ResultSet은 next() 메서드를 사용하여 다음 로우로 이동
➡️ 커서를 최초 데이터의 위치로 이동시키려면 ResultSet을 사용하기 전에 rs.next() 메서드를 한 번 호출
· 대부분은 다음과 같이 executeQuery() 메서드를 수행한 후 while(rs.next())와 같이 더 이상 로우가 없을 때까지 루프를 돌면서 데이터를 처리하는 방법을 사용. 이 때 로우에서 각 컬럼값을 가져오려면 rs.getXxx() 메서드를 사용
ResultSet rs = psmt.executeQuery();
while(rs.next()) {
name = rs.getString(1); // or rs.getString("name");
age = rs.getInt(2); // or rs.getInt("age");
}
rs.close();
🔎 getXxx() 메서드에서 컬럼을 지정하는 방법으로 해당 컬럼의 index 값(1부터 시작) 이나 컬럼 이름을 사용
🔎 가급적 index보다는 컬럼 이름을 사용하는 편이 코드 이해나 유지보수에 더 유리
🔎 ResultSet의 사용이 끝났으면 rs.close() 메서드를 사용하여 ResultSet을 닫아 주어야 함
📌 6단계 : 연결 해제
· 데이터베이스와 연결을 관리하는 Connection 인스턴스는 사용한 후 반납하지 않으면 계속 연결을 유지
· 데이터베이스 연결은 해당 연결을 이용한 작업이 모두 끝나는 시점에서 close() 메서드를 사용하여 해제해야 함
conn.close();
4) 주요 클래스
(1) Statement 주요 메서드
boolean execute(String sql)
|
👾 주어진 SQL문 sql을 실행
- select 구문을 실행하는 경우에는 true를 리턴, 그렇지 않은 경우에는 false 리턴 - true를 리턴하는 경우에는 getResultSet() 메서드를 이용하여 ResultSet 객체를 생성 - update, insert, delete 구문을 사용하는 경우에는 false를 리턴하고, getUpdateCount() 메서드를 이용하여 영향받은 행의 갯수를 알아낼수 있음 |
ResultSet executeQuery(String sql)
|
👾 select 구문을 실행할 때 사용
|
int executeUpdate(String sql)
|
👾 select를 제외한 나머지 insert, create, update, delete 구문을 실행할 때 사용
- 이 때 영향을 받은 행의 개수를 리턴 |
ResultSet getResultSet()
|
👾 현재 SQL 구문을 실행한 결과를 리턴
- select 구문을 실행했을 경우에만 유효 |
int getUpdateCount()
|
👾 현재 SQL 구문의 실행으로 영향을 받은 행의 개수를 리턴
- select를 제외한 나머지 구문에서만 유효 |
(2) ResultSet
👩🏻💻 Statement 객체의 getResultSet(), executeQuery() 메서드가 리턴하는 객체로서 select 구문 실행 결과를 다룰 때 사용
👩🏻💻 select 구문을 실행하여 ResultSet 객체가 생성되면 커서 cursor 가 만들어지고 select 구문 실행 결과를 가르킴
boolean next()
|
👾 커서를 다음 행으로 이동
- ResultSet 객체가 처음 생성된 직후에 next() 메서드를 한 번 호출해야 첫 번째 행을 커서가 가르키게 됨 - 성공적으로 커서가 이동하면 true를 리턴하고 더 이상 없어서 커서를 이동시킬 수 없으면 false를 리턴 |
boolean previous()
|
👾 커서를 이전 행으로 이동
- 성공적으로 커서가 이동하면 true를 리턴하고 더 이상 결과가 없어서 커서를 이동시킬 수 없으면 false를 리턴 |
Statement getStatement()
|
👾 현재 ResultSet을 생성시킨 Statement 객체를 리턴
|
<자료형> get<자료형>(String colName),
<자료형> get<자료형>(int colIndex) |
👾 colName에 지정된 속성명에 해당하는 실제 데이터를 리턴
- 예를 들어 속성의 데이터 자료형이 String 형과 호환되는 속성이라면 getString() 메서드를 사용 - 속성 이름 대신 속성의 위치 정보를 colIndex로 줄 수 있음 맨 앞의 속성은 '1', 두 번째 속성은 '2'와 같이 숫자로 속성의 위치를 지정 |
(3) PreparedStatement
👩🏻💻 Statement 객체의 execute계열 메서드는 모두 SQL 문을 컴파일하고 바로 수행시켜서 결과를 리턴
👩🏻💻 PreparedStatement 객체는 SQL 문을 미리 컴파일하여 실행하기 직전의 상태로 만든 후 실제 실행은 나중에 필요에 따라 할 수 있음
👩🏻💻 같은 SQL 문을 여러 번 실행시켜야 하는 경우에 는 Statement 객체보다 PreparedStatement 객체 사용이 더 효과적
👩🏻💻 PreparedStatement 객체로 생성되는 SQL 문은 마치 함수처럼 매개변수를 설정, 필요에 따라 매개변수의 값을 바꿔 실행가능
➡️ 비슷한 SQL 구문을 반복적으로 실행시켜야 하는 경우에도 유용
➡️ 매개변수를 정의할 때에는 '?' 을 사용하고 매개변수에 값을 설정할때에는 set계열 메서드를 사용
📌 DBMS와 Java의 자료형 변환
· DBMS에서의 컬럼의 자료형과 Java 자료형, 그리고 관련된 JDBC 메소드 간의 변환표
DBMS 자료형
|
Java 자료형
|
ResultSet 메서드
|
PreparedStatement 메서드
|
CHAR
|
String
|
getString
|
setString
|
VARCHAR
|
String
|
getString
|
setString
|
DECIMAL
|
java.math.BigDecimal
|
getBigDecimal
|
setBigDecimal
|
NUMBER
|
java.math.BigDecimal
|
getBigDecimal
|
setBigDecimal
|
TINYINT
|
byte
|
getByte
|
setByte
|
SMALLINT
|
short
|
getShort
|
setShort
|
INTEGER
|
int
|
getInt
|
setInt
|
BIGINT
|
long
|
getLong
|
setLong
|
REAL
|
float
|
getFloat
|
setFloat
|
FLOAT
|
double
|
getDouble
|
setDouble
|
DOUBLE
|
double
|
getDouble
|
setDouble
|
DATE
|
java.sql.Date
|
getDate
|
setDate
|
TIME
|
java.sql.Time
|
getTime
|
setTime
|
CLOB
|
Clob
|
getClob
|
setClob
|
BLOB
|
Blob
|
getBlob
|
setBlob
|
TIMESTAMP
|
java.sql.Timestamp
|
getTimestamp
|
setTimestamp
|
[ 내용 참고 : IT 학원 수업 내용 ]
'Database > MySQL' 카테고리의 다른 글
[MySQL] INNER JOIN / OUTER JOIN / CROSS JOIN / SELF JOIN (2) | 2024.02.25 |
---|---|
[MySQL] JDBC 예제 (0) | 2024.02.25 |
[MySQL] 데이터베이스 모델링 | 참조 무결성 (1) | 2024.02.25 |
[MySQL] 데이터베이스 모델링 | 1~3 정규화, 역정규화 (1) | 2024.02.25 |
[MySQL] 데이터베이스 모델링 | 진행단계, 분류, 엔티티, 관계 (0) | 2024.02.25 |