게시물 생성 기능
▷ 실행 결과
▶ BoardManager4 클래스
메인 메뉴에서 '1. Create' 선택 시, 새로운 게시물의 제목, 내용, 작성자를 키보드로 입력받고,
보조 메뉴에서 '1.Ok'를 선택 시, boards 테이블에 새로운 게시물이 저장되도록 해보자.
package bbs.mariadb.controller;
import static bbs.mariadb.util.BbsIO.p;
import static bbs.mariadb.util.BbsIO.pl;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
import bbs.mariadb.model.Board;
// 실제 게시판을 관리하는 클래스
public class BoardManager4 {
//화면에 게시글 목록 출력 메서드
// 멤버변수
private Scanner scanner;
private Connection conn;
// 멤버상수
private final String JDBC_DRIVER = "org.mariadb.jdbc.Driver";
private final String JDBC_URL = "jdbc:mariadb://localhost/thisisjava";
private final String USER = "root";
private final String PASSWORD = "mariadb";
// 생성자
public BoardManager4(){
scanner = new Scanner(System.in);
createConnection(); // 속성메서드로 생성한 후, 생성자에서 호출하는 방식
}
public void createConnection() {
try {
// 드라이버 로딩
Class.forName(JDBC_DRIVER);
// MariaDB와 연결
conn = DriverManager.getConnection(
JDBC_URL, USER, PASSWORD);
} catch(Exception e) {
e.printStackTrace();
exit();
}
}
// 기능메서드
public void list(){
pl(""); // 화면에 빈줄 출력
pl(" >>> [게시물 목록] <<< ");
pl("-----------------------------------------------------");
// %-6s : 왼쪽 정렬(-), 총 크기(6칸), 문자열 출력
System.out.printf("%-6s%-12s%-16s%-40s\n",
"no", "writer", "date", "title");
//no writer date title
pl("-----------------------------------------------------");
// 데모 게시글로, 나중에 주석처리할 예정
// System.out.printf("%-6s%-12s%-16s%-40s\n",
// "1", "봄", "2023-05-30", "게시판을 만들었어요^^;");
// System.out.printf("%-6s%-12s%-16s%-40s\n",
// "2", "여름", "2023-06-01", "앗! 1등을 노렸는데...");
// System.out.printf("%-6s%-12s%-16s%-40s\n",
// "3", "가을", "2023-06-02", "올 여름은 비가 너무 온대요");
// 데모 게시글 끝
// 진짜 게시물 목록 출력 시작
String sql = """
SELECT bno, btitle, bcontent, bwriter, bdate
FROM boards
ORDER BY bno DESC ;
""";
// 가장 최근 게시물부터 보기 위해 내림차순 정렬
try {
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
while(rs.next()) { // rs가 레코드를 갖는다면, 루프문을 반복해라
Board board = new Board(); // DTO객체인 board에 데이터를 모두 담을 계획
board.setBno(rs.getInt("bno"));
board.setBtitle(rs.getString("btitle"));
board.setBcontent(rs.getString("bcontent"));
board.setBwriter(rs.getString("bwriter"));
board.setBdate(rs.getDate("bdate"));
// board 내용 출력
System.out.printf("%-6s%-12s%-16s%-40s\n",
board.getBno(),
board.getBwriter(),
board.getBdate(),
board.getBtitle());
}
// 진짜 게시물 목록 출력 끝
// while문 이후 연결 끊기
rs.close();
pstmt.close();
} catch(SQLException e) {
e.printStackTrace();
exit(); // 에러가 날 경우, 종료시킴
}
// list()메서드 내에서 하단에 출력될 메인메뉴 호출
mainMenu();
}
// 화면 하단에 메인메뉴 메서드
public void mainMenu(){
pl("");
pl("=====================================================");
pl("메인 메뉴 : 1. Create | 2. Read | 3. Clear | 4. Exit ");
p("메뉴 선택 : ");
// 스캐너 이용 메뉴를 선택함 -> 변수 menuNo에 저장
String menuNo = scanner.nextLine();
// 선택한 메뉴 처리 시작
switch(menuNo) {
case "1" : // 1. Create를 선택한 경우
create();
break;
case "2" : // 2. Read를 선택한 경우
read();
break;
case "3" : // 3. Clear를 선택한 경우
clear();
break;
case "4" : // 4. Exit를 선택한 경우
exit();
break;
default :
pl("메뉴를 잘못 선택하셨습니다.");
list(); // 2+) 재귀 호출 -> 공유방 문서 확인
// list()메서드가 계속 자기자신을 호출하는 상황
// -> 입력 스트림( = Scanner 객체)에 의해 blocking되어
// 재귀를 빠져나갈 수 있음
break;
} // 선택한 메뉴처리 끝
}
// 메뉴별 각각의 메서드 정의
// 1. Create() 메서드
public void create() {
// * 1 ) 자료 입력받기 시작
// ❶ 먼저 비어있는 새로운 DTO 객체 생성
Board boardDTO = new Board(); // *4 디버그 중단점
pl("[ 새로운 게시물을 입력해주세요.]");
p("제목 : ");
boardDTO.setBtitle(scanner.nextLine());
// ❷ 스캐너로부터 입력받은 내용을 boardDTO의 제목에 저장
p("내용 : ");
boardDTO.setBcontent(scanner.nextLine());
p("작성자 : ");
boardDTO.setBwriter(scanner.nextLine());
// * 자료 입력받기 끝
// * 2 ) 보조 메뉴 출력 : 자료 저장하기 전 확인하기 대화창
pl("=====================================================");
// 메뉴 출력
pl("보조 메뉴 : 1. Ok | 2. Cancel ");
// 메뉴 선택하는 입력창
p("메뉴 선택 : ");
String menuNo = scanner.nextLine();
// 선택된 메뉴 번호 처리
if (menuNo.equals("1")) {
// MariaDB에 새 게시물 저장 => 이 블럭 실행 후, list()메서드 호출 시, 기능중복되므로 호출하면 안됨
// (1) INSERT sql 문자열을 만든다
String sql = """
INSERT INTO boards
(btitle, bcontent, bwriter, bdate)
VALUES (?, ?, ?, now());
""";
PreparedStatement pstmt;
try {
// (2) PreparedStatement 준비
pstmt = conn.prepareStatement(sql);
// (3) PreparedStatement 객체의 파라미터를 저장한다
pstmt.setString(1, boardDTO.getBtitle());
pstmt.setString(2, boardDTO.getBcontent());
pstmt.setString(3, boardDTO.getBwriter());
// (4) PreparedStatement 객체 질의문 실행
pstmt.executeUpdate();
// (5) PreparedStatement 객체 종료
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
exit();
} catch (Exception e) {
e.printStackTrace();
exit();
}
} //else {
// 입력취소 -> 목록으로 돌아감 => 사실 불필요함(if문 아래 list()메서드 호출 하므로)
//}
list();
}
// 2. Read() 메서드
public void read() {
pl("*** read() 메서드 실행됨 ");
list();
}
// 3. Clear() 메서드
public void clear() {
pl("*** clear() 메서드 실행됨 ");
list();
}
// 4. Exit() 메서드
public void exit() {
// 프로그램을 종료함
// 0 : 프로그램이 잘 종료되었다는 의미
pl("\n*** 프로그램 종료 ***");
System.exit(0);
}
}
① 스캐너로부터 입력받은 문자열을 변수 menuNo에 저장
② menuNo가 1일 경우, 보조메뉴의 '1.Ok'를 의미하므로 새로운 정보가 게시물에 저장됨
이 때, ==가 아닌 equals( ) 메서드를 이용해 비교 ( ∵ 참조 주소가 아닌 문자열의 내용이 같은지 비교 )
게시물 읽기 기능
▷ 실행 결과
▶ BoardManager5 클래스
메인 메뉴에서 '2. Read' 선택 시, 게시물의 번호를 키보드로 입력받고, boards 테이블에 있는 해당 게시물을 가져와서 출력해보자.
package bbs.mariadb.controller;
import static bbs.mariadb.util.BbsIO.p;
import static bbs.mariadb.util.BbsIO.pl;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
import bbs.mariadb.model.Board;
// 실제 게시판을 관리하는 클래스
public class BoardManager5 {
//화면에 게시글 목록 출력 메서드
// 멤버변수
private Scanner scanner;
// Connection 객체는 BoardManager3 클래스 전역에서 사용해야 하므로 멤버변수로 선언
private Connection conn;
// 멤버상수
private final String JDBC_DRIVER = "org.mariadb.jdbc.Driver";
private final String JDBC_URL = "jdbc:mariadb://localhost/thisisjava";
private final String USER = "root";
private final String PASSWORD = "mariadb";
// 생성자
public BoardManager5(){
scanner = new Scanner(System.in); // *3 디버그
createConnection(); // 속성메서드로 생성한 후, 생성자에서 호출하는 방식
}
// 기능메서드
public void createConnection() {
try {
// 드라이버 로딩
Class.forName(JDBC_DRIVER);
// MariaDB와 연결
conn = DriverManager.getConnection(
JDBC_URL, USER, PASSWORD);
} catch(Exception e) {
e.printStackTrace();
exit();
}
}
public void list(){
pl(""); // 화면에 빈줄 출력
pl(" >>> [게시물 목록] <<< ");
pl("-----------------------------------------------------");
// %-6s : 왼쪽 정렬(-), 총 크기(6칸), 문자열 출력
System.out.printf("%-6s%-12s%-16s%-40s\n",
"no", "writer", "date", "title");
//no writer date title
pl("-----------------------------------------------------");
// 데모 게시글로, 나중에 주석처리할 예정
// System.out.printf("%-6s%-12s%-16s%-40s\n",
// "1", "봄", "2023-05-30", "게시판을 만들었어요^^;");
// System.out.printf("%-6s%-12s%-16s%-40s\n",
// "2", "여름", "2023-06-01", "앗! 1등을 노렸는데...");
// System.out.printf("%-6s%-12s%-16s%-40s\n",
// "3", "가을", "2023-06-02", "올 여름은 비가 너무 온대요");
// 데모 게시글 끝
// 진짜 게시물 목록 출력 시작
String sql = """
SELECT bno, btitle, bcontent, bwriter, bdate
FROM boards
ORDER BY bno DESC ;
""";
// 가장 최근 게시물부터 보기 위해 내림차순 정렬
try {
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
while(rs.next()) { // rs가 레코드를 갖는다면, 루프문을 반복해라
Board board = new Board(); // DTO객체인 board에 데이터를 모두 담을 계획
board.setBno(rs.getInt("bno"));
board.setBtitle(rs.getString("btitle"));
board.setBcontent(rs.getString("bcontent"));
board.setBwriter(rs.getString("bwriter"));
board.setBdate(rs.getDate("bdate"));
// board 내용 출력
System.out.printf("%-6s%-12s%-16s%-40s\n",
board.getBno(),
board.getBwriter(),
board.getBdate(),
board.getBtitle());
}
// 진짜 게시물 목록 출력 끝
// while문 이후에 연결 끊기
rs.close();
pstmt.close();
} catch(SQLException e) {
e.printStackTrace();
exit(); // 에러가 날 경우, 종료시킴
}
// list()메서드 내에서 하단에 출력될 메인메뉴 호출
mainMenu();
}
// 화면 하단에 메인메뉴 메서드
public void mainMenu(){
pl("");
pl("=====================================================");
pl("메인 메뉴 : 1. Create | 2. Read | 3. Clear | 4. Exit ");
p("메뉴 선택 : ");
// 스캐너 이용 메뉴를 선택함 -> 변수 menuNo에 저장
String menuNo = scanner.nextLine();
// 선택한 메뉴 처리 시작
switch(menuNo) {
case "1" : // 1. Create를 선택한 경우
create();
break;
case "2" : // 2. Read를 선택한 경우
read();
break;
case "3" : // 3. Clear를 선택한 경우
clear();
break;
case "4" : // 4. Exit를 선택한 경우
exit();
break;
default :
pl("메뉴를 잘못 선택하셨습니다.");
list(); // 2+) 재귀 호출 -> 공유방 문서 확인
// list()메서드가 계속 자기자신을 호출하는 상황
// -> 입력 스트림( = Scanner 객체)에 의해 blocking되어
// 재귀를 빠져나갈 수 있음
break;
} // 선택한 메뉴처리 끝
}
// 메뉴별 각각의 메서드 정의
// 1. Create() 메서드
public void create() {
// 1 자료 입력하기 시작 -> 먼저 비어있는 새로운 DTO 객체 생성
Board boardDTO = new Board(); // *4 디버그 중단점
pl("[ 새로운 게시물을 입력해주세요.]");
p("제목 : ");
boardDTO.setBtitle(scanner.nextLine()); // 스캐너로부터 입력받은 내용을 boardDTO의 제목에 저장
p("내용 : ");
boardDTO.setBcontent(scanner.nextLine());
p("작성자 : ");
boardDTO.setBwriter(scanner.nextLine());
// 4+)1 자료 입력하기 끝
// 4+)2 자료 저장하기 전 확인하기 대화창
// => 보조메뉴 출력
pl("=====================================================");
// 메뉴 출력
pl("보조 메뉴 : 1. Ok | 2. Cancel ");
// 메뉴 선택하는 입력창
p("메뉴 선택 : ");
String menuNo = scanner.nextLine();
// 선택된 메뉴 번호 처리
if (menuNo.equals("1")) { // ==이 아닌 equals로 비교한 이유 : 클래스 객체의 내용물(값) 비교
// -> 주소비교가 아닌, 내용물이 같은지 비교해야 함(주소비교 시, 참조주소가 아닌 이상 다르다고 나옴)
// MariaDB에 새 게시물 저장 => 이 블럭 실행 후, list()메서드 호출 시, 기능중복되므로 호출하면 안됨
// (1) INSERT sql 문자열을 만든다
String sql = """
INSERT INTO boards
(btitle, bcontent, bwriter, bdate)
VALUES (?, ?, ?, now());
""";
PreparedStatement pstmt;
try {
// (2) PreparedStatement 준비
pstmt = conn.prepareStatement(sql);
// (3) PreparedStatement 객체의 파라미터를 저장한다
pstmt.setString(1, boardDTO.getBtitle());
pstmt.setString(2, boardDTO.getBcontent());
pstmt.setString(3, boardDTO.getBwriter());
// (4) PreparedStatement 객체 질의문 실행
pstmt.executeUpdate();
// (5) PreparedStatement 객체 종료
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
exit();
} catch (Exception e) {
e.printStackTrace();
exit();
}
} //else {
// 입력취소 -> 목록으로 돌아감 => 사실 불필요함(if문 아래 list()메서드 호출 하므로)
//}
list();
}
// *
// 2. Read() 메서드
public void read() { // *5 디버그 중단점
// 보조메뉴 구현 : 상세 자료 보기할 게시물 번호 입력
pl("---[ 게시물 읽기 ]---");
p("bno : ");
// int bno = scanner.nextLine();
int bno = Integer.parseInt(scanner.nextLine());
// MariaDB로부터 레코드 가져오기
try {
String sql = """
SELECT
bno, btitle, bcontent, bwriter, bdate
FROM boards
WHERE bno = ? ;
"""; // bno가 PRIMARY KEY이므로 데이터가 하나만 나옴
PreparedStatement pstmt = conn.prepareStatement(sql);
// sql의 파라미터에 인수 지정
pstmt.setInt(1, bno);
// 쿼리 실행
ResultSet rs = pstmt.executeQuery();
if(rs.next()) {
// board DTO 객체에 레코드 저장
Board board = new Board();
board.setBno(rs.getInt("bno"));
board.setBtitle(rs.getString("btitle"));
board.setBcontent(rs.getString("bcontent"));
board.setBwriter(rs.getString("bwriter"));
board.setBdate(rs.getDate("bdate"));
// 저장한 레코드를 화면에 출력합니다. => 추후 View 클래스로 분리
pl("#################################");
pl("번호 : " + board.getBno());
pl("제목 : " + board.getBtitle());
pl("내용 : " + board.getBcontent());
pl("작성자 : " + board.getBwriter());
pl("날짜 : " + board.getBdate());
pl("#################################");
}
rs.close();
pstmt.close();
} catch(SQLException e) {
e.printStackTrace();
exit(); // 문제 발생 시, 프로그램 종료
}
// 메서드 실행이 잘 되었는지 확인은 list()메서드 호출로 가능
// 만약 문제가 있다면 exit()메서드로 프로그램 종료
list();
}
// 3. Clear() 메서드
public void clear() {
pl("*** clear() 메서드 실행됨 ");
list();
}
// 4. Exit() 메서드
public void exit() {
// 프로그램을 종료함
// 0 : 프로그램이 잘 종료되었다는 의미
pl("\n*** 프로그램 종료 ***");
System.exit(0);
}
}
① scanner.nextLine( ) 메서드 : String 타입 → 타입 변환 필수!
주석 처리된 부분은 에러 발생 : Type mismatch: cannot convert from String to int
게시물 수정 기능
▷ 실행 결과
▶ BoardManager6 클래스
// * 수정폼을 먼저 보인 후, 수정 요청이 OK이면 수정 / 아니면 list() 메서드 호출
public void update(Board board){
// 1. 수정 내용 입력 받기
// 번호는 기본키 속성이므로 수정 불가
pl("[수정 내용 입력]");
p("제목 : ");
board.setBtitle(scanner.nextLine());
p("내용 : ");
board.setBcontent(scanner.nextLine());
p("작성자 : ");
board.setBwriter(scanner.nextLine());
// 2. 보조 메뉴 출력 - 수정한 내용을 저장할 것인지 취소할 것인지 확인
pl("---------------------------------------");
pl("보조 메뉴 : 1. Ok | 2. Cancel");
p("메뉴 선택 : ");
String menuNo = scanner.nextLine();
// 보조메뉴 선택이 2개뿐이므로 switch문 대신 if구문 사용
if (menuNo.equals("1")) {
// 쿼리 내용 작성 및 SQL 작성
try {
String sql = """
UPDATE boards
SET
btitle = ?,
bcontent = ?,
bwriter = ?
WHERE bno = ? ;
""";
PreparedStatement pstmt = conn.prepareStatement(sql);
// ?에 값을 대입
pstmt.setString(1, board.getBtitle());
pstmt.setString(2, board.getBcontent());
pstmt.setString(3, board.getBwriter());
pstmt.setInt(4, board.getBno());
// 질의문 실행
int updateCount = pstmt.executeUpdate();
// pstmt 종료
pstmt.close();
} catch(Exception e) {
e.printStackTrace();
// 문제가 있는 경우, 프로그램 자동 종료
exit();
}
}
// 업데이트 결과, 수정된 내용을 보여주는 목록으로 돌아가기
list();
// 어차피 list() 메서드 호출로 확인 가능 -> else 필요 없음
// else {
//
// }
}
// 6++) 선택된 자료번호 삭제 기능
public void delete(Board board) {
// boards 테이블에서 실제 데이터 삭제
try {
String sql = """
DELETE FROM boards WHERE bno = ?;
""";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, board.getBno());
int updateCount = pstmt.executeUpdate();
pstmt.close();
} catch(Exception e) {
e.printStackTrace();
// 문제가 있는 경우, 프로그램 자동 종료
exit();
}
// 게시물 목록 출력
list();
}
'백엔드 > JAVA' 카테고리의 다른 글
입출력 스트림 (0) | 2023.06.11 |
---|---|
게시판 구현 (1) (0) | 2023.06.02 |
데이터 입출력 (2) (0) | 2023.05.31 |
데이터 입출력(1) (0) | 2023.05.30 |
JDBC 드라이버 다운로드 및 등록 (0) | 2023.05.23 |