mini-pms 37 a

8 minute read

Client

37-a 데이터 관리를 DBMS에게 맡기기 : JDBC API 사용하기

01) 프로젝트에 JDBC 드라이버를 설정한다.

  • build.gradle 변경
    • mvnrepository.com 또는 search.maven.org에서 mariadb jdbc driver를 검색한다.
    • 라이브러리 정보를 build.gradle 파일에 설정한다.
    • gradle을 이용하여 eclipse 설정 파일을 갱신한다.
      • $ gradle eclipse
      • 다운로드 받지 않은 라이브러리가 있다면 자동으로 서버에서 받을 것이다.
      • 라이브러리 정보가 변경되었다면 해당 라이브러리를 서버에서 받을 것이다.
    • 이클립스 프로젝트를 리프래시 한다.
      • 프로젝트에 mariadb jdbc driver 라이브러리가 추가되었는지 확인한다.

02) DBMS에 게시글을 저장할 테이블을 생성한다.

  • 기존 프로젝트와의 중복을 피하기 위해 pms_board를 사용한다.
create table pms_board(
  no int not null,
  title varchar(255) not null,
  content text not null,
  writer varchar(30) not null,
  cdt datetime default now(),
  vw_cnt int default 0
);

alter table pms_board
  add constraint pms_board
_pk primary key(no);

alter table pms_board
  modify column no int not null auto_increment;

03) DBMS를 이용하여 게시글을 저장하고 로딩한다.

  • https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/Connection.html#createStatement()
  • https://hyeonstorage.tistory.com/111

com.eomcs.pms.listener.DataHandlerListener 변경

- 게시글 관련 데이터를 파일에서 로딩하고 파일로 저장하는 코드를 제거한다.

com.eomcs.pms.handler.BoardAddCommand 변경

  • 데이터를 저장할 때 JDBC API를 사용한다.
public class BoardAddCommand implements Command {

  // 데이터 리스트와 관련된 코드를 삭제한다.
  //  List<Board> boardList;
  //
  //  public BoardDeleteCommand(List<Board> list) {
  //    this.boardList = list;
  //  }

  @Override
  public void execute() {
    System.out.println("[게시물 등록]");

    Board board = new Board();
    board.setTitle(Prompt.inputString("제목? "));
    board.setContent(Prompt.inputString("내용? "));
    board.setWriter(Prompt.inputString("작성자? "));

    // DriverManager 클래스를 통해 데이터 원본에 JDBC 드라이버를 통하여
    // 커넥션을 만드는 역할을 한다.

    // Connection 인터페이스가 구현된 Connection 객체를 사용해서 SQL문을
    // 정의하고 실행시킬 수 있는 Statement 객체를 생성한다.

    // Statement 객체는 Connection 객체에 의해 리턴되는 객체에 의해 구현되는
    // 일종의 메서드 집합.
    try (Connection con = DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/studydb?user=study&password=1111");
        Statement stmt = con.createStatement()) {

    // SQL 문을 String에 담아서 실행시킨다.
      String sql = String.format(
          "insert into pms_board
        (title,content,writer) values('%s','%s','%s')",
          board.getTitle(), board.getContent(), board.getWriter());
      stmt.executeUpdate(sql);

      System.out.println("게시글을 등록하였습니다.");

    } catch (Exception e) {
      System.out.println("게시글 등록 중 오류 발생");
      e.printStackTrace();
    }
  }
}

com.eomcs.pms.handler.BoardListCommand 변경

  • 데이터를 조회할 때 JDBC API를 사용한다.
public class BoardListCommand implements Command {

  // 리스트와 연관된 코드 삭제
  //  List<Board> boardList;
  //
  //  public BoardListCommand(List<Board> list) {
  //    this.boardList = list;
  //  }


  @Override
  public void execute() {
    System.out.println("[게시물 목록]");

    //    Iterator<Board> iterator = boardList.iterator();

    while (iterator.hasNext()) {
      //  Board board = iterator.next();
      System.out.printf("%d, %s, %s, %s, %d\n",
          board.getNo(),
          board.getTitle(),
          board.getWriter(),
          board.getRegisteredDate(),
          board.getViewCount());
    }
  }
}
public class BoardListCommand implements Command {

  @Override
  public void execute() {
    System.out.println("[게시물 목록]");

    try (Connection con = DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/studydb?user=study&password=1111");
        Statement stmt = con.createStatement()) {

      // 리스트를 보여줄 sql 문을 작성한다.
      // select 문으로 검색된 데이터를 no 내림차순으로 정렬한다.
      String sql = "select no, title, writer, cdt, vw_cnt"
          + " from pms_board
        "
          + " order by no desc";

      // PreparedStatement 객체 내에서 sql 문을 실행하고
      // 그 결과로 발생된 ResultSet 객체를 리턴한다.
      try (ResultSet rs = stmt.executeQuery(sql)) {
        System.out.println("번호, 제목, 작성자, 등록일, 조회수");
        while (rs.next()) {
          System.out.printf("%d, %s, %s, %s, %d\n",
              rs.getInt("no"),
              rs.getString("title"),
              rs.getString("witer"),
              rs.getDate("cdt"),
              rs.getInt("vw_cnt"));
        }
      }
    } catch (Exception e) {
      System.out.println("게시글 목록 조회 중 오류 발생");
      e.printStackTrace();
    }
  }
}

com.eomcs.pms.handler.BoardDetailCommand 변경

  • 데이터를 조회할 때 JDBC API를 사용한다.
public class BoardDetailCommand implements Command {

  // 삭제
  //  List<Board> boardList;
  //
  //  public BoardDetailCommand(List<Board> list) {
  //    this.boardList = list;
  //  }

  @Override
  public void execute() {
    System.out.println("[게시물 상세보기]");
    int no = Prompt.inputInt("번호? ");
    //    Board board = findByNo(no);

    if (board == null) {
      System.out.println("해당 번호의 게시글이 없습니다.");
      return;
    }

    //    board.setViewCount(board.getViewCount() + 1);

    System.out.printf("제목: %s\n", board.getTitle());
    System.out.printf("내용: %s\n", board.getContent());
    System.out.printf("작성자: %s\n", board.getWriter());
    System.out.printf("등록일: %s\n", board.getRegisteredDate());
    System.out.printf("조회수: %d\n", board.getViewCount());
  }

  //  private Board findByNo(int no) {
  //    for (int i = 0; i < boardList.size(); i++) {
  //      Board board = boardList.get(i);
  //      if (board.getNo() == no) {
  //        return board;
  //      }
  //    }
  //    return null;
  //  }
}
public class BoardDetailCommand implements Command {

  @Override
  public void execute() {
    System.out.println("[게시물 상세보기]");
    int no = Prompt.inputInt("번호? ");

    try (Connection con = DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/studydb?user=study&password=1111");
        Statement stmt = con.createStatement()) {

      String sql = String.format(
          "select no, title, content, writer, cdt, vw_cnt"
              + " from pms_board
            "
              + " where no = %d", no);

      try (ResultSet rs = stmt.executeQuery(sql)) {
        // rs.next() 커서를 하나씩 옮겨가며 이동한다.
        if (rs.next()) {
          System.out.printf("제목: %s\n", rs.getString("title"));
          System.out.printf("내용: %s\n", rs.getString("content"));
          System.out.printf("작성자: %s\n", rs.getString("writer"));
          System.out.printf("등록일: %s\n", rs.getDate("cdt"));

          // 처음 보자마자 조회수 1이 뜨게 한다.
          System.out.printf("조회수: %d\n", rs.getInt("vw_cnt") + 1);

          // 조회수가 증가하도록 sql 문을 실행한다.
          sql = String.format("update pms_board
         set vw_cnt = vw_cnt + 1"
              + " where no = %d", no);
          stmt.executeUpdate(sql);
        } else {
          System.out.println("해당 번호의 게시물이 존재하지 않습니다.");
        }
      }
    } catch (Exception e) {
      System.out.println("게시글 상세 조회 중 오류 발생");
      e.printStackTrace();
    }
  }
}

com.eomcs.pms.handler.BoardUpdateCommand 변경

  • 데이터를 변경할 때 JDBC API를 사용한다.

public class BoardUpdateCommand implements Command {

  // 삭제
  //  List<Board> boardList;
  //
  //  public BoardUpdateCommand(List<Board> list) {
  //    this.boardList = list;
  //  }

  @Override
  public void execute() {
    System.out.println("[게시물 변경]");
    int no = Prompt.inputInt("번호? ");
    //    Board board = findByNo(no);

    if (board == null) {
      System.out.println("해당 번호의 게시글이 없습니다.");
      return;
    }

    String title = Prompt.inputString(
        String.format("제목(%s)? ", board.getTitle()));
    String content = Prompt.inputString(
        String.format("내용(%s)? ", board.getContent()));
    String writer = Prompt.inputString(
        String.format("작성자(%s)? ", board.getWriter()));

    String response = Prompt.inputString("정말 변경하시겠습니까?(y/N) ");
    if (!response.equalsIgnoreCase("y")) {
      System.out.println("게시글 변경을 취소하였습니다.");
      return;
    }

    board.setTitle(title);
    board.setContent(content);
    board.setWriter(writer);
    System.out.println("게시글을 변경하였습니다.");
  }

  //  private Board findByNo(int no) {
  //    for (int i = 0; i < boardList.size(); i++) {
  //      Board board = boardList.get(i);
  //      if (board.getNo() == no) {
  //        return board;
  //      }
  //    }
  //    return null;
  //  }
}
public class BoardUpdateCommand implements Command {

  @Override
  public void execute() {
    System.out.println("[게시물 변경]");
    int no = Prompt.inputInt("번호? ");

    // 타이틀과 컨텐트 변수를 준비한다.
    String title = null;
    String content = null;

    try (Connection con = DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/studydb?user=study&password=1111");
        Statement stmt = con.createStatement()) {

      String sql = String.format(
          "select title, content from pms_board
         where no = %d", no);

      // 변경 전 게시글 내용을 가져온다.
      try (ResultSet rs = stmt.executeQuery(sql)) {
        if (rs.next()) {
          title = rs.getString("title");
          content = rs.getString("content");
        } else {
          System.out.println("해당 번호의 게시글이 존재하지 않습니다.");
          return;
        }
      }
    } catch (Exception e) {
      System.out.println("게시글 조회 중 오류 발생");
      e.printStackTrace();
    }

    // title 과 content에 새로운 정보를 입력받는다.
    title = Prompt.inputString(String.format("제목(%s)? ", title));
    content = Prompt.inputString(String.format("내용(%s)? ", content));

    String response = Prompt.inputString("정말 변경하시겠습니까?(y/N) ");
    if (!response.equalsIgnoreCase("y")) {
      System.out.println("게시글 변경을 취소하였습니다.");
      return;
    }

    // 다시 데이터 베이스에 접속한다.
    try (Connection con = DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/studydb?user=study&password=1111");
        Statement stmt = con.createStatement()) {

      // sql 문을 이용하여 title과 content의 변경 내용을 저장한다.
      String sql = String.format(
          "update pms_board
         set title = '%s', content = '%s' where no = %d",
          title, content, no);

      int count = stmt.executeUpdate(sql);

      if (count == 0) {
        System.out.println("해당 번호의 게시물일 존재하지 않습니다.");
      } else {
        System.out.println("게시글을 변경하였습니다.");
      }
    } catch (Exception e) {
      System.out.println("게시글 변경 중 오류 발생");
      e.printStackTrace();
    }
  }
}

com.eomcs.pms.handler.BoardDeleteCommand 변경

  • 데이터를 삭제할 때 JDBC API를 사용한다.
public class BoardDeleteCommand implements Command {

  // 데이터 리스트와 관련된 코드를 삭제한다.
  //  List<Board> boardList;
  //
  //  public BoardDeleteCommand(List<Board> list) {
  //    this.boardList = list;
  //  }

  @Override
  public void execute() {
    System.out.println("[게시물 삭제]");
    int no = Prompt.inputInt("번호? ");
    //    int index = indexOf(no);

    if (index == -1) {
      System.out.println("해당 번호의 게시글이 없습니다.");
      return;
    }

    String response = Prompt.inputString("정말 삭제하시겠습니까?(y/N) ");
    if (!response.equalsIgnoreCase("y")) {
      System.out.println("게시글 삭제를 취소하였습니다.");
      return;
    }

    boardList.remove(index);
    System.out.println("게시글을 삭제하였습니다.");
  }

  // 게시물 번호를 검증하는 것은 데이터 베이스가 해주기 때문에 삭제한다.
  //  private int indexOf(int no) {
  //    for (int i = 0; i < boardList.size(); i++) {
  //      Board board = boardList.get(i);
  //      if (board.getNo() == no) {
  //        return i;
  //      }
  //    }
  //    return -1;
  //  }
}
public class BoardDeleteCommand implements Command {

  @Override
  public void execute() {
    System.out.println("[게시물 삭제]");
    int no = Prompt.inputInt("번호? ");

    String response = Prompt.inputString("정말 삭제하시겠습니까?(y/N) ");
    if (!response.equalsIgnoreCase("y")) {
      System.out.println("게시글 삭제를 취소하였습니다.");
      return;
    }

    // 데이터 베이스와 연결
    try (Connection con = DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/studydb?user=study&password=1111");
        Statement stmt = con.createStatement()) {

      // 데이터베이스의 no를 사용하여 데이터를 삭제한다.
      String sql = String.format("delete from pms_board
     where no=%d", no);

      // 삭제가 실행된다면 몇개가 실행되는지 리턴되고 실행되지 않으면 count는 0이 된다.
      int count = stmt.executeUpdate(sql);

      // count가 0 일때는 게시글이 없다는 화면을 출력한다.
      if (count == 0) {
        System.out.println("해당 번호의 게시글이 없습니다.");
        return;
      }
      System.out.println("게시글을 삭제하였습니다.");
    } catch (Exception e) {
      System.out.println("게시글 삭제 중 오류 발생");
      e.printStackTrace();
    }
  }
}

com.eomcs.pms.App 변경

  • BoardXxxCommand 변경에 맞춰 소스 코드를 정리한다.
public class App {
.
.
.
    public void service() throws Exception {

        notifyApplicationContextListenerOnServiceStarted();

        List<Member> memberList = (List<Member>) context.get("memberList");
        List<Project> projectList = (List<Project>) context.get("projectList");
        List<Task> taskList = (List<Task>) context.get("taskList");

        Map<String,Command> commandMap = new HashMap<>();

        // boardList를 사용하지 않기 때문에 boardList를 파라미터로 넘겼던 것을 삭제한다.
        commandMap.put("/board/add", new BoardAddCommand());
        commandMap.put("/board/list", new BoardListCommand());
        commandMap.put("/board/detail", new BoardDetailCommand());
        commandMap.put("/board/update", new BoardUpdateCommand());
        commandMap.put("/board/delete", new BoardDeleteCommand());
.
.
.
}

04) DBMS에 회원 정보를 저장할 테이블을 만들고, 이 테이블을 사용하여 회원 정보를 관리한다.

create table pms_member(
  no int not null,
  name varchar(30) not null,
  email varchar(50) not null,
  password varchar(50) not null,
  photo varchar(255),
  tel varchar(20),
  cdt datetime default now()
);

alter table pms_member
  add constraint pms_member_pk primary key(no);

alter table pms_member
  modify column no int not null auto_increment;
  • com.eomcs.pms.listener.DataHandlerListener 변경
    • 회원 관련 데이터를 파일에서 로딩하고 파일로 저장하는 코드를 제거한다.
  • com.eomcs.pms.handler.MemberXxxCommand 변경
    • 데이터를 저장하고 조회, 변경, 삭제할 때 JDBC API를 사용한다.
  • com.eomcs.pms.App 변경
    • MemberXxxCommand 변경에 맞춰 소스 코드를 정리한다.

05) DBMS에 프로젝트 정보를 저장할 테이블을 만들고, 이 테이블을 사용하여 프로젝트 정보를 관리한다.

create table pms_project(
  no int not null,
  title varchar(255) not null,
  content text not null,
  sdt date not null,
  edt date not null,
  owner varchar(30) not null,
  members varchar(255) not null
);

alter table pms_project
  add constraint pms_project_pk primary key(no);

alter table pms_project
  modify column no int not null auto_increment;
  • com.eomcs.pms.listener.DataHandlerListener 변경
    • 프로젝트 관련 데이터를 파일에서 로딩하고 파일로 저장하는 코드를 제거한다.
  • com.eomcs.pms.handler.ProjectXxxCommand 변경
    • 데이터를 저장하고 조회, 변경, 삭제할 때 JDBC API를 사용한다.
  • com.eomcs.pms.App 변경
    • ProjectXxxCommand 변경에 맞춰 소스 코드를 정리한다.

06) DBMS에 작업 정보를 저장할 테이블을 만들고, 이 테이블을 사용하여 작업 정보를 관리한다.

create table pms_task(
  no int not null,
  content text not null,
  deadline date not null,
  owner varchar(30) not null,
  status int default 0
);

alter table pms_task
  add constraint pms_task_pk primary key(no);

alter table pms_task
  modify column no int not null auto_increment;
  • com.eomcs.pms.listener.DataHandlerListener 삭제
    • 이제 더이상 파일 입출력 기능이 필요 없다.
  • com.eomcs.pms.handler.TaskXxxCommand 변경
    • 데이터를 저장하고 조회, 변경, 삭제할 때 JDBC API를 사용한다.
  • com.eomcs.pms.App 변경
    • TaskXxxCommand 변경에 맞춰 소스 코드를 정리한다.

Categories:

Updated: