[JDBC] JDBC의 작업순서 | 게시판 만들기 실습 (1.board 테이블 설계 ~ 2.Java 프로젝트 생성)
JDBC란?
JDBC(Java Database Connectivity)는 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API이다. JDBC는 데이터베이스에서 자료를 쿼리하거나 업데이트하는 방법을 제공한다.
출처: 위키백과
Java --- Server 연결?
Server로 MySQL 쓰다가 Oracle 쓰려고 할 때?
즉, 서버를 새로 연결할 때 마다 .java 파일(MysqlToJava.. OracleToJava..)을 만들어야 할까?
→ No, 이는 너무 번거롭다.
자바 프로젝트와 데이터베이스 간의 연결하는 공통 설명서가 있으면 편리하다! → API
데이터베이스를 제공하는 업체(MySQL, Oracle..)들이 API에 맞추어 파일을 만들어온다! → .jar
결국, 자바프로젝트는 .jar파일을 가져다 쓰기만 하면 된다.
JDBC의 작업순서
그렇다면, JDBC는 어떻게 동작할까?
- 1. JDBC 사용하겠다. 즉 Driver를 로딩한다.
- 2. DB연결 (Connection 생성)
- 3. SQL 준비 및 실행
- 4. DB 연결 해제 (종료)
여기서 3, 4 의 과정을 보다 자세히 알아보자.
3. SQL 준비 및 실행
- 준비? 2가지의 상태가 존재한다.
(1) Statement
(2) PreparedStatement
- 실행? 각 CRUD 역할에 따라 2가지의 메소드가 존재한다.
(1) executeQuery() : R
-> 결과값으로 ResultSet이 반환된다. 이 테이블에 맨 위 행(속성row의 바로 아래로, 데이터가 시작되는 행)과 맨 아래행은 데이터가 없다. 중간에만 데이터가 채워지는데, 이 때 커서는 맨 위를 가리킨다. rs.next()로 밑 행으로 하나씩 이동한다. 데이터가 없는 행에 도착하면 끝남 while(rs.next()). 위처럼 데이터를 가공한다.
(2) executeUpdate() : C, U, D
-> 공통점? 테이블의 변화. 결과값을 반환할 필요가 없다. 몇 개의 행을 건드렸는지, 넣었는지 개수가 반환되나 이를 활용할 수도 안 할 수도.
참고로 데이터의 CRUD를 하는 DML에는 이러한 명령어가 존재한다.
cf. DML -> INSERT SELECT UPDATE DELETE (CRUD)
4. DB 연결 해제 (종료). 연결 해제 시 연결했던 역순으로 끊는다
(1) rs 끊기 if(rs != null) // null이 아니면 .close()
(2) st / pst 끊기
(3) connection 끊기
<실습> 게시판 만들기
1. MySQL에서 board 테이블 설계하기
- board 테이블을 생성하는데 필요한 내용은 다음과 같다.
- id : INT AUTOINCREMENT PK
- writer : VARCHAR(20) NOT NULL
- title : VARCHAR(50) NOT NULL
- content : TEXT
- view_cnt : INT DEFAULT 0
- reg_date : TIMESTAMP DEFAULT now()
- 위를 바탕으로 MySQL에서 쿼리문을 작성해보자.
CREATE DATABASE dearbeany_board DEFAULT CHARACTER SET utf8mb4;
USE dearbeany_board;
CREATE TABLE board(
id INT AUTO_INCREMENT,
writer VARCHAR(20) NOT NULL,
title VARCHAR(50) NOT NULL,
content TEXT,
view_cnt INT DEFAULT 0,
reg_date TIMESTAMP DEFAULT now(),
PRIMARY KEY(id)
);
INSERT INTO board(title, writer, content)
VALUES("파친코", "이민진", "역사에 외면당한 재일조선인 가족의 대서사극"),
("불편한 편의점2", "김호연", "불편한데 자꾸 가고싶은 편의점");
SELECT * FROM board;
- 아래는 SQL문을 실행한 결과이다.
2. Java Project 생성하기
- 이클립스 > 자바 프로젝트 생성 > lib 폴더 안에 mysql-connector.jar 추가해준 후 > build 경로에 Add jar 해주기
-DTO(Data Transfer Object) : 데이터를 가지고 왔다갔다 하기 위해 쓰는 바구니
JDBCTest.java
/*
* 1. JDBC 드라이버 로드
* 2. 데이터베이스 연결 (Connection 생성)
* 3. SQL 준비 및 실행
* 4. 데이터베이스 연결 해제
*/
public class JDBCTest {
// 드라이버는 매번 아닌, 한 번만 생성해두고 사용한다
// 기본 생성자를 만들어서 객체 생성 한 번 할 때 드라이버도 한 번만 생성해서 계속 사용할 수 있도록 한다
public JDBCTest() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
System.out.println("드라이버 로딩 성공");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JDBCTest jdbctest = new JDBCTest();
for (Board b : jdbctest.selectAll()) {
System.out.println(b);
}
}
private List<Board> selectAll() {
List<Board> list = new ArrayList<>();
// try-catch 구문 밖에서 생성해야
// finally 에서 close 해줄 수 있다
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// url은 MySQL 전용임
String url = "jdbc:mysql://localhost:3306/dearbeany_board?serverTimezone=UTC";
// 연결
// Connection은 인터페이스이므로 new로 생성할 수 없어서
// DriverManager로부터 Connection을 얻어온다
conn = DriverManager.getConnection(url, "연결할 DB의 아이디", "DB의 비밀번호");
// SQL 준비
String sql = "SELECT * FROM board";
// 연결 후 쿼리문을 담아서 날리기 위한 용도의 객체
stmt = conn.createStatement();
// sql을 날린 후 결과값으로 rs를 받아옴
rs = stmt.executeQuery(sql);
while (rs.next()) {
// 컬럼의 이름을 알던지(columnLabel), 순서를 알던지 해야 함(columnLabel)
// 단 순서를 사용할 경우 sql은 인덱스가 1부터 시작함을 주의!!
int id = rs.getInt("id");
String writer = rs.getString("writer");
String title = rs.getString("title");
String content = rs.getString("writer");
int viewCnt = rs.getInt("view_cnt");
String regDate = rs.getString("reg_date");
Board board = new Board(id, title, writer, content, regDate, viewCnt);
list.add(board);
}
// 이곳에서 연결을 해제할 경우 쿼리작성을 내 실수로 에러가 발생했을 때
// catch 구문으로 넘어가면서 제대로 이곳이 실행되지 않는다. 즉 연결해제가 안 된다
// 따라서 finally 구문에서 연결해제 해야한다
// rs.close();
// stmt.close();
// conn.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
}
파일을 실행할 경우 출력결과는 다음과 같다. DB와 연결된 결과를 확인해보았다.
그러나, 위와 같은 경우 매우 비효율적인 문제가 발생한다!
예를 들어, 새로운 insert() 메소드를 추가하려고 한다.
selectAll() 내부에서 했던 Connection 생성 > Statment 생성 > ResultSet 받아오기 > try-catch 구문 ..
이러한 작업들을 또 반복해서 사용하나?
→ No, 이는 매우 비효율적이다. 따라서 이러한 작업들을 클래스로 빼서 한 곳에 쓰고 직접 관리하자!
즉, 우리는 DBUtil 클래스를 따로 만들어서 관리하도록 하자!
2022.09.25 - [분류 전체보기] - [JDBC] 게시판 만들기 (3. DBUtil 클래스 생성 ~ 4. CRUD 완성 및 테스트)