dearbeany
[JDBC] 게시판 만들기 (3. DBUtil 클래스 생성 ~ 4. CRUD 완성 및 테스트) 본문
3. DBUtil 클래스 생성
→ DBUtil을 그 때마다 new 로 생성하지 말고, 한 번 생성해놓고 계속 쓰도록 하자. 싱글턴을 사용해서!
private static DBUtil instance = new DBUtil();
private DBUtil() {
}
public static DBUtil getInstace() {
return instance;
}
- DBUtil을 사용할 준비가 되었으니, JDBCTest.java의 역할을 DBUtil로 빼서 작성해보도록 하자.
public class DBUtil {
// MySql 드라이버 클래스 이름
private final String driverName = "com.mysql.cj.jdbc.Driver";
// DB와 연결하기 위해 필요한 URL
private final String url = "jdbc:mysql://localhost:3306/dearbeany_board?serverTimezone=UTC";
// USER 정보
private final String username = "DB연결할 유저의 아이디";
private final String password = "DB연결할 유저의 비밀번호";
private static DBUtil instance = new DBUtil();
private DBUtil() {
// JDBC 드라이버를 로딩
try {
Class.forName(driverName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static DBUtil getInstace() {
return instance;
}
/**
* DriverManager를 통해 내 userid, password를 이용해 Connection을 반환하는 메서드
*
* @return Connection
* @throws SQLException
*/
public Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
// ...가변인자를 사용하여 값이 몇개가 넘어오든 알아서 묶어서 반복할 수 있게끔 알아서 처리한다
public void close(AutoCloseable... autoCloseables) {
for (AutoCloseable ac : autoCloseables) {
if (ac != null) {
try {
ac.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
4.DAO 를 통해 CRUD 하기
- 직접적으로 DB와 Java가 소통할 수 있도록 왔다갔다하게 하는 역할을 DAO(Data Access Object) 라고 한다.
- DAO 인터페이스(BoardDao.java)와 이를 implements한 클래스(BoardDaoImpl.java)를 생성하도록 하자.
- 참고로 인터페이스에서는 메소드의 선언을, 클래스에서는 메소드의 구현을 한다.
cf. 인터페이스의 역할?
- 강제로 기능을 구현하게 한다
- 다형성, 추상화
- 나중에 다른 구현을 했을 때 갈아끼기 쉽다.
BoardDao.java
- 다음과 같이 CRUD 역할을 하는 6개의 메소드를 구현할 것이다. 각각의 역할에 해당하는 메소드는 다음과 같다.
- C(Create) : insertBoard
- R(Read) : selectAll, selectOne
- U(Update) : updateBoard, updateViewCnt
- D(Delete) : deleteBoard
public interface BoardDao {
// 전체 게시판의 내용(게시글) 다 가져온다
public List<Board> selectAll();
// ID에 해당하는 게시글 하나 가져온다
public Board selectOne(int id);
// 게시글을 등록한다
public void insertBoard(Board board);
// 게시글을 삭제한다
public void deleteBoard(int id);
// 게시글을 수정한다
public void updateBoard(Board board);
// 조회수를 증가한다
public void updateViewCnt(int id);
}
* 본격적으로 메소드를 구현하기 전에 주의할 점이 존재한다. (지난 포스팅 참고)
2022.09.25 - [분류 전체보기] - [JDBC] JDBC의 작업순서 | 게시판 만들기 실습 (1.board 테이블 설계 ~ 2.Java 프로젝트 생성)
* Statement vs PreparedStatement 차이?
- Statement는 sql문을 미리 완성해놓고 날려야 하나,
- PreparedStatement는 물음표를 이용하여 동적으로 원하는 값을 집어넣을 수가 있다.
* executeQuery vs exeCuteUpdate 차이?
- 바로 JDBC의 작업순서 중 (3)단계인데, CRUD의 역할에 따라 2개의 메소드(executeQuery, executeUpdate)가 존재하는 것이다.
- executeQuery의 경우 R(read)를 하기 때문에 반환되는 결과값인 ResultSet을 꼭 활용한다. 즉, SELECT의 경우 해당!
- 반면 executeUpdate의 경우 C, R, D에선 결과값을 반환할 필요가 없다.
BoardDaoImpl.java
1. insertBoard() 메소드를 작성해보도록 하자. (CRUD 중 Create)
public void insertBoard(Board board) throws SQLException {
// 미리 sql 문 만들어 놓고 PreparedStatement 객체를 만들어서
// ?에 대신 값을 채우도록 하자
String sql = "INSERT INTO board (title, writer, content) VALUES (?,?,?)";
// DB 접속해서 사용하게끔 쓰자
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = util.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, board.getTitle()); // 첫 번째 물음표에 board가 가진 title 값을 세팅
pstmt.setString(2, board.getWriter()); // 두 번째 물음표에 board가 가진 writer 값을 세팅
pstmt.setString(3, board.getContent()); // 세 번째 물음표에 content 값을 세팅
pstmt.executeUpdate(); // 데이터를 변경해야 하므로 update를 날린다
// stmt.executeQuery(sql) 와는 다르다. 이미 sql문을 위에 다 만들어놓고 데이터 변경만 하면 되기 때문
} finally {
util.close(pstmt, conn);
}
}
insertBoard() 메소드를 테스트 해보면?
public class Test {
public static void main(String[] args) {
BoardDao dao = BoardDaoImpl.getInstace();
Board board = new Board("빠르게 실패하기", "존 크럼볼츠", "빠르게 성공하고 싶은 법을 알려준다");
try {
dao.insertBoard(board);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Test 파일을 Run하고 워크벤치에서 SELECT로 조회해본다.
아래와 같이 데이터가 잘 추가된 것을 확인해볼 수 있다!
*** MySql은 자동으로 AutoCommit이 설정되어있다.
2. selectAll() 메소드도 완성해보자. (CRUD 중 Read)
public List<Board> selectAll() {
String sql = "SELECT * FROM board";
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
List<Board> list = new ArrayList<>();
try {
conn = util.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
while (rs.next()) {
int id = rs.getInt("id");
String writer = rs.getString("writer");
String title = rs.getString("title");
String content = rs.getString("content");
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 (SQLException e) {
e.printStackTrace();
} finally {
util.close(rs, stmt, conn);
}
return list;
}
이를 Test 파일에서 메소드를 호출하여 결과를 출력해보면?
다음과 같이 모두 조회되는 것을 확인해볼 수 있다.
3. selectOne() 메소드 (CRUD 중 Read)
public Board selectOne(int id) {
String sql = "SELECT * FROM board WHERE id = ?";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
Board board = new Board();
try {
conn = util.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
rs = pstmt.executeQuery();
while (rs.next()) {
board.setId(rs.getInt(1));
board.setWriter(rs.getString(2));
board.setTitle(rs.getString(3));
board.setContent(rs.getString(4));
board.setViewCnt(rs.getInt(5));
board.setRegDate(rs.getString(6));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
util.close(conn, pstmt, rs);
}
return board;
}
id가 1인 게시글을 확인해보자. 아래와 같이 잘 출력되는 것을 확인할 수 있다.
4. deleteBoard() - CRUD 중 D(delete)
public void deleteBoard(int id) throws SQLException {
String sql = "DELETE FROM board WHERE id = ?";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = util.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id); // 첫 번째 자리에 id를 넣는다
pstmt.executeUpdate();
} finally {
util.close(pstmt, conn);
}
}
id가 3인 게시글을 삭제하니 다음과 같이 잘 출력되는 것을 확인할 수 있다.
5. updateViewCnt() - CRUD 중 U(update)
public void updateViewCnt(int id) throws SQLException {
String sql = "UPDATE board SET view_cnt = view_cnt+1 WHERE id = ?";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = util.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
pstmt.executeUpdate();
} finally {
util.close(pstmt, conn);
}
}
id가 2인 게시글에 대하여 메소드를 실행하였다. 파일을 2번 Run하니, id 가 2인 게시글의 ViewCnt가 2로 증가했음을 확인할 수 있다.
6. updateBoard() - CRUD 중 U(update)
- 게시글에 대하여 title과 content를 바꾸도록 한다.
public void updateBoard(Board board) throws SQLException {
String sql = "UPDATE board SET title = ?, content = ? WHERE id = ?";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = util.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, board.getTitle());
pstmt.setString(2, board.getContent());
pstmt.setInt(3, board.getId());
pstmt.executeUpdate();
} finally {
util.close();
}
}
Test.java에서 테스트 해보자!
public class Test {
public static void main(String[] args) {
BoardDao dao = BoardDaoImpl.getInstace();
Board board = dao.selectOne(2); // id가 2번인 게시글을 가져온다
try {
// title, content 를 변경하고
board.setTitle("불편한 편의점1");
board.setContent("청파동을 배경으로 한 김호연의 신간");
// 변경한 내용으로 update 하기
dao.updateBoard(board);
} catch (SQLException e) {
e.printStackTrace();
}
// 전체 게시판 글을 모두 출력해보면
for (Board b : dao.selectAll()) {
System.out.println(b);
}
}
}
다음과 같이 업데이트 된 내용을 출력할 수 있다.
'Web' 카테고리의 다른 글
[JDBC&Web] MVC 모델로 게시판 만들기, CRUD 실습 (0) | 2022.09.26 |
---|---|
[JDBC] JDBC의 작업순서 | 게시판 만들기 실습 (1.board 테이블 설계 ~ 2.Java 프로젝트 생성) (0) | 2022.09.25 |
[MySQL] 집계함수의 결과를 group by 없이 출력하기 (OVER) (0) | 2022.09.15 |
[Bootstrap] ToDoList 스타일 꾸며보기 (0) | 2022.08.30 |
[ToDoList] 추가, 삭제 기능 구현 및 로컬스토리지 이용 (0) | 2022.08.30 |