Web

[JDBC] JDBC의 작업순서 | 게시판 만들기 실습 (1.board 테이블 설계 ~ 2.Java 프로젝트 생성)

dearbeany 2022. 9. 25. 16:21

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 완성 및 테스트)