네이버클라우드 AIaaS 개발자 양성과정 1기/DBMS, SQL, JDBC, Servlet

[비트캠프] 68일차(14주차5일) - JDBC: myapp-36~37

끈기JK 2023. 2. 10. 14:00

 

36. DB 커넥션 공유

 

① 이전

JdbcBoardDao 에서 insert() 한다. 그러면 DBMS 로 Connection 생성 : 연결 하고 SQL 전달 한다.

이때 Authentication(이름) : 사용자 유효 여부 검사(ID/PWD 일치 여부) → Authorization(권한) : 사용자의 권한 검사(database 접근 가능?, SQL 명령 사용범위) 한다. => "Auth"

DBMS 에서 결과 리턴 및 연결 끊기 한다.

매번 연결할 때 문제점 : 시간 소요! => 해결책? DB 커넥션 공유

 

JdbcBoardDao 에서 findAll() 한다. 그러면 DBMS 로 Connection 생성 : 연결 하고 SQL 전달 한다.

DBMS 에서 결과 리턴 및 연결 끊기 한다.

 

SQL 실행할 때마다 즉 DAO 의 메서드 호출때 마다 DBMS 에 연결하고 작업이 끝나면 연결을 끊는다.

 

*시스템 간의 데이터 공유

인사시스템 에서 계정/비번 으로 hradmin/1112 입력하고 all 권한을 HR Database 에 사용한다.

회계시스템 에서 계정/비번 으로 acadmin/1133 입력하고 all 건한을 회계 Database 에 사용한다.

 

방법1

회계시스템에서 직원정보요청을 인사시스템에 하고 JSON 이나 XML 을 받는다.

이기종 시스템 간의 데이터 교환

- vendor 가 다르다 = DB 접근 차단

- Platform 이 다르다 (C#; java) = JSON, XML 로 데이터를 주고 받는다.

= System Integration (SI)

 

회계시스템 개발자 : 인사시스템으로 부터 직원 정보를 받아서 처리하고 기능 개발 => 기존 시스템과 연계 => SI

인사시스템 유지보수 개발자 : 회계시스템에서 요청한 서비스를 개발 => 기존 시스템에 새 기능 추가 => SM

회계시스템에서 계정/비번 으로 hrguest/2222 입력하고 select 권한을 HR Database 에 사용한다.

 

 

② DB 커넥션 공유

Client 1, 2 마다 JdbcBoardDao, JdbcStudentDao, JdbcTeacherDao 에서 Connection 을 사용한다.

Client App 마다 1개의 Connection 만 생성한다.

 

### 36. Connection 객체 공유하기 
- Connection 객체 공유하는 이유 및 방법

 

Jdbc----Dao 생성자에 Connection 객체 주입받는 것으로 바꾼다.

public class JdbcBoardDao implements BoardDao {

  Connection con;

  // 의존객체 Connection 을 생성자에서 받는다.
  public JdbcBoardDao(Connection con) {
    this.con = con;
  }
public class JdbcStudentDao implements StudentDao {

  Connection con;

  // 의존객체 Connection 을 생성자에서 받는다.
  public JdbcStudentDao(Connection con) {
    this.con = con;
  }
public class JdbcTeacherDao implements TeacherDao {

  Connection con;

  // 의존객체 Connection 을 생성자에서 받는다.
  public JdbcTeacherDao(Connection con) {
    this.con = con;
  }

 

ClientApp 에서 Dao 객체 생성시 con 주입한다.

public class ClientApp {

  public static void main(String[] args) {
    new ClientApp().execute("localhost", 8888);
  }

  void execute(String ip, int port) {
    try (Connection con = DriverManager.getConnection(
        "jdbc:mariadb://localhost:3306/studydb", "study", "1111")) {

      // DAO 객체들끼리 Connection 객체를 공유한다.
      JdbcBoardDao boardDao = new JdbcBoardDao(con);
      JdbcStudentDao studentDao = new JdbcStudentDao(con);
      JdbcTeacherDao teacherDao = new JdbcTeacherDao(con);

 

 

 

37. Application Server Architecture

 

① 기존 방식

각 PC 마다 App 이 설치되어 있다.

기능 추가/변경/삭제를 한다면?

각 App 을 재설치 해야한다 = 유지보수가 불편하다. App. 의 기능 변경이 잦은 경우 더욱 더 유지보수가 힘들다!

 

② App 을 서버에서 실행 → "Application Server (AS)"

각 PC 마다 Client 가 있다. Server 와 연결하여 사용한다.

Client 는 사용자 입력을 받아서 서버에 전달하고, 서버의 응답을 출력한다.

 

Server의 기능 추가/변경/삭제를 한다면? 서버만 변경하면 된다!

Server 는 기능 실행, UI 생성 한다.

왜?

global business(세계화, 가속) → 경쟁 가열 → 제품 생명 주기가 짧아짐 → 부서/인사 변경이 잦아짐, 업무 변경이 잦아짐 → App. 기능 변경이 잦아짐 → 서버에서 실행하는 방식

 

 

 

Application Server 프로젝트 구조

 

app-client 를 분리해 app-client (UI 제공, 사용자 입/출력), app-server (기능 수행) (↔ DBMS) 으로 나눈다.

 

 

 

Application Server 의 Client / Server 구조

 

사용자가 ① 입력을 Client App 에 하면 여기서 ② 전달을 Server App 으로 한다. Handler 가 실행 하고 ④ 응답을 Clientapp 에 한다. ⑤ 출력 한다.

Handler 는 DAO 의 Con 객체 사용하여 DBMS 와 통신한다.

 

 

 

통신 규칙 (protocol)

 

Client 에서 Server 로 writeUTF() 보낸다. Server 에서 readUTF() 로 읽는다.

Server 에서 Client 로 writeUTF() 보낸다. Client 에서 readUTF() 로 읽는다.

이 요청/응답을 반복한다.

 

 

 

전송

 

이전 방식

[서버] 에서 한 줄 보내면 [클라이언트] 에서 한 줄 받는다. 이걸 반복하다가 [[END]] 보내면 연결 끊는다.

 

개선 방식

버퍼 기능 추가해서 버퍼에 문자 담는다. [서버] 에서 한 번 보내고 [클라이언트] 에서 한 번 받는다.

 

 

 

StringWriter 의 활용

 

PrintWriter 는 StringWriter 를 사용해 버퍼의 문자열을 담는 메모리를 이용한다. PrintWriter 의 print(), println(), printf() 메서드를 이용하면 버퍼에 보관 된다. stringWriter.toString 하면 문자열로 변환되고 writeUTF() 안에 넣어 DataOutputStream 통해 전달한다. DataOutputStream 은 Socket OutputStream 통해 Client 로 전달한다.

 

 

메서드 생성시 레퍼런스 필드에 저장된 메서드에 위임하려면 이클립스에서 

Source > Generate Delegate Methods... 선택한다.

 

### 37. Application Server 구조로 전환하기 
- 애플리케이션 서버 아키텍처의 특징과 구현

 

 

public class ServerApp {

  Connection con;
  StudentHandler studentHandler;
  TeacherHandler teacherHandler;
  BoardHandler boardHandler;
  HelloHandler helloHandler = new HelloHandler();

  public static void main(String[] args) {
    try {
      new ServerApp().execute(8888);
    } catch (Exception e) {
      System.out.println("서버 실행 오류!");
      e.printStackTrace();
    }
  }

  public ServerApp() throws Exception {
    this.con = DriverManager.getConnection(
        "jdbc:mariadb://localhost:3306/studydb", "study", "1111");

    JdbcBoardDao boardDao = new JdbcBoardDao(con);
    JdbcStudentDao studentDao = new JdbcStudentDao(con);
    JdbcTeacherDao teacherDao = new JdbcTeacherDao(con);

    this.studentHandler = new StudentHandler("학생", studentDao);
    this.teacherHandler = new TeacherHandler("강사", teacherDao);
    this.boardHandler = new BoardHandler("게시판", boardDao);
  }

  void execute(int port) {

    try (Connection con = this.con;
        ServerSocket serverSocket = new ServerSocket(port)) {
      System.out.println("서버 실행 중...");

      try (Socket socket = serverSocket.accept();
          DataOutputStream out = new DataOutputStream(socket.getOutputStream());
          DataInputStream in = new DataInputStream(socket.getInputStream())) {

        // 입출력 보조 도구 준비
        StreamTool streamTool = new StreamTool(in, out);

        String clientIP = socket.getInetAddress().getHostAddress();
        System.out.printf("접속: %s\n", clientIP);

        hello(streamTool);
        processRequest(streamTool);

        System.out.printf("끊기: %s\n", clientIP);

      } catch (Exception e) {
        System.out.println("클라이언트 요청 처리 오류!");
        e.printStackTrace();
      }

    } catch (Exception e) {
      System.out.println("서버 소켓 오류!");
      e.printStackTrace();
    }
  }

  private void hello(StreamTool streamTool) throws Exception {
    streamTool.println("비트캠프 관리 시스템")
    .println("  Copyright by 네이버클라우드1기")
    .println("------------------------------------")
    .println("안녕하세요!")
    .println()
    .send();
  }

  private void processRequest(StreamTool streamTool) throws Exception {

    loop: while (true) {
      String command = streamTool.readString();

      if (command.equals("menu")) {
        menu(streamTool);
        continue;
      }

      int menuNo;
      try {
        menuNo = Integer.parseInt(command);
      } catch (Exception e) {
        streamTool.println("메뉴 번호가 옳지 않습니다!").println().send();
        continue;
      }

      try {
        switch (menuNo) {
          case 1:
            studentHandler.service(streamTool);
            break;
          case 2:
            teacherHandler.service(streamTool);
            break;
          case 3:
            boardHandler.service(streamTool);
            break;
          case 4:
            helloHandler.service(streamTool);
            break;
          case 9:
            break loop; // loop 라벨이 붙은 while 문을 나간다.
          default:
            streamTool.println("잘못된 메뉴 번호 입니다.").send();
        }

      } catch (Exception e) {
        streamTool.printf("명령 실행 중 오류 발생! - %s : %s\n",
            e.getMessage(),
            e.getClass().getSimpleName()).send();
      }
    }

    // while 종료하면 클라이언트와 연결을 끊는다.
    streamTool.print("quit").send();

  }

  void menu(StreamTool streamTool) throws Exception {
    streamTool.println("1. 학생관리")
    .println("2. 강사관리")
    .println("3. 게시판")
    .println("4. 인사")
    .println("9. 종료")
    .println("메뉴 번호:")
    .send();
  }

}

 

HelloHandler 생성한다.

public class HelloHandler {

  public void service(StreamTool streamTool) throws Exception {
    streamTool.println("안녕하세요!!!").send();
  }

}

 

public class BoardHandler {

  private BoardDao boardDao;
  private String title;

  public BoardHandler(String title, BoardDao boardDao) {
    this.title = title;
    this.boardDao = boardDao;
  }

  private void inputBoard(StreamTool streamTool) throws Exception {
    Board b = new Board();
    b.setTitle(streamTool.promptString("제목? "));
    b.setContent(streamTool.promptString("내용? "));
    b.setPassword(streamTool.promptString("암호? "));

    this.boardDao.insert(b);
    streamTool.println("입력했습니다!").send();
  }

  private void printBoards(StreamTool streamTool) throws Exception {
    streamTool.println("번호\t제목\t작성일\t조회수");

    Board[] boards = this.boardDao.findAll();

    for (Board b : boards) {
      streamTool.printf("%d\t%s\t%s\t%d\n",
          b.getNo(), b.getTitle(), b.getCreatedDate(), b.getViewCount());
    }
    streamTool.send();
  }

  private void printBoard(StreamTool streamTool) throws Exception {
    int boardNo = streamTool.promptInt("게시글 번호? ");

    Board b = this.boardDao.findByNo(boardNo);

    if (b == null) {
      streamTool.println("해당 번호의 게시글 없습니다.").send();
      return;
    }

    streamTool
    .printf("    제목: %s\n", b.getTitle())
    .printf("    내용: %s\n", b.getContent())
    .printf("  등록일: %s\n", b.getCreatedDate())
    .printf("  조회수: %d\n", b.getViewCount());
    b.setViewCount(b.getViewCount() + 1);

    streamTool.send();
  }

  private void modifyBoard(StreamTool streamTool) throws Exception {
    int boardNo = streamTool.promptInt("게시글 번호? ");

    Board old = this.boardDao.findByNo(boardNo);

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

    // 변경할 데이터를 저장할 인스턴스 준비
    Board b = new Board();
    b.setNo(old.getNo());
    b.setCreatedDate(old.getCreatedDate());
    b.setTitle(streamTool.promptString(String.format("제목(%s)? ", old.getTitle())));
    b.setContent(streamTool.promptString(String.format("내용(%s)? ", old.getContent())));
    b.setPassword(streamTool.promptString("암호? "));
    b.setViewCount(old.getViewCount());

    if (!old.getPassword().equals(b.getPassword())) {
      streamTool.println("암호가 맞지 않습니다!").send();
      return;
    }

    String str = streamTool.promptString("정말 변경하시겠습니까?(y/N) ");
    if (str.equalsIgnoreCase("Y")) {
      this.boardDao.update(b);
      streamTool.println("변경했습니다.");
    } else {
      streamTool.println("변경 취소했습니다.");
    }
    streamTool.send();
  }

  private void deleteBoard(StreamTool streamTool) throws Exception {
    int boardNo = streamTool.promptInt("게시글 번호? ");

    Board b = this.boardDao.findByNo(boardNo);

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

    String password = streamTool.promptString("암호? ");
    if (!b.getPassword().equals(password)) {
      streamTool.println("암호가 맞지 않습니다!").send();
      return;
    }

    String str = streamTool.promptString("정말 삭제하시겠습니까?(y/N) ");
    if (!str.equalsIgnoreCase("Y")) {
      streamTool.println("삭제 취소했습니다.").send();
      return;
    }

    this.boardDao.delete(b);

    streamTool.println("삭제했습니다.").send();
  }

  private void searchBoard(StreamTool streamTool) throws Exception {
    String keyword = streamTool.promptString("검색어? ");

    Board[] boards = this.boardDao.findByKeyword(keyword);

    streamTool.println("번호\t제목\t작성일\t조회수");

    for (Board b : boards) {
      streamTool.printf("%d\t%s\t%s\t%d\n",
          b.getNo(), b.getTitle(), b.getCreatedDate(), b.getViewCount());
    }
    streamTool.send();
  }

  public void service(StreamTool streamTool) throws Exception {

    menu(streamTool);

    while (true) {

      String command = streamTool.readString();

      if (command.equals("menu")) {
        menu(streamTool);
        continue;
      }

      int menuNo;
      try {
        menuNo = Integer.parseInt(command);
      } catch (Exception e) {
        streamTool.println("메뉴 번호가 옳지 않습니다!").println().send();
        continue;
      }

      try {
        switch (menuNo) {
          case 0:
            streamTool.println("메인화면으로 이동!").send();
            return;
          case 1: this.inputBoard(streamTool); break;
          case 2: this.printBoards(streamTool); break;
          case 3: this.printBoard(streamTool); break;
          case 4: this.modifyBoard(streamTool); break;
          case 5: this.deleteBoard(streamTool); break;
          case 6: this.searchBoard(streamTool); break;
          default:
            streamTool.println("잘못된 메뉴 번호 입니다.");
        }
      } catch (Exception e) {
        streamTool.printf("명령 실행 중 오류 발생! - %s : %s\n",
            e.getMessage(),
            e.getClass().getSimpleName()).send();
      }
    }
  }

  void menu(StreamTool streamTool) throws Exception {
    streamTool.printf("[%s]\n", this.title)
    .println("1. 등록")
    .println("2. 목록")
    .println("3. 조회")
    .println("4. 변경")
    .println("5. 삭제")
    .println("6. 검색")
    .println("0. 이전")
    .send();
  }
}

 

public class TeacherHandler {

  private TeacherDao teacherDao;
  private String title;

  public TeacherHandler(String title, TeacherDao teacherDao) {
    this.title = title;
    this.teacherDao = teacherDao;
  }

  private void inputTeacher(StreamTool streamTool) throws Exception {
    Teacher m = new Teacher();
    m.setName(streamTool.promptString("이름? "));
    m.setTel(streamTool.promptString("전화? "));
    m.setEmail(streamTool.promptString("이메일? "));
    m.setDegree(streamTool.promptInt("1. 고졸\n2. 전문학사\n3. 학사\n4. 석사\n5. 박사\n0. 기타\n학위? "));
    m.setSchool(streamTool.promptString("학교? "));
    m.setMajor(streamTool.promptString("전공? "));
    m.setWage(streamTool.promptInt("강의료(시급)? "));

    this.teacherDao.insert(m);

    streamTool.println("입력했습니다!").send();
  }

  private void printTeachers(StreamTool streamTool) throws Exception {

    Object[] teachers = this.teacherDao.findAll();

    streamTool.println("번호\t이름\t전화\t학위\t전공\t시강료");

    for (Object obj : teachers) {
      Teacher m = (Teacher) obj;
      streamTool.printf("%d\t%s\t%s\t%s\t%s\t%d\n",
          m.getNo(), m.getName(), m.getTel(),
          getDegreeText(m.getDegree()), m.getMajor(), m.getWage());
    }
    streamTool.send();
  }

  private void printTeacher(StreamTool streamTool) throws Exception {
    int teacherNo = streamTool.promptInt("강사번호? ");

    Teacher m = this.teacherDao.findByNo(teacherNo);

    if (m == null) {
      streamTool.println("해당 번호의 강사가 없습니다.").send();
      return;
    }

    streamTool
    .printf("    이름: %s\n", m.getName())
    .printf("    전화: %s\n", m.getTel())
    .printf("  이메일: %s\n", m.getEmail())
    .printf("    학위: %s\n", getDegreeText(m.getDegree()))
    .printf("    학교: %s\n", m.getSchool())
    .printf("    전공: %s\n", m.getMajor())
    .printf("  강의료: %s\n", m.getWage())
    .printf("  등록일: %s\n", m.getCreatedDate())
    .send();
  }

  private void modifyTeacher(StreamTool streamTool) throws Exception {
    int teacherNo = streamTool.promptInt("강사번호? ");

    Teacher old = this.teacherDao.findByNo(teacherNo);

    if (old == null) {
      System.out.println("해당 번호의 강사가 없습니다.");
      return;
    }

    // 변경할 데이터를 저장할 인스턴스 준비
    Teacher m = new Teacher();
    m.setNo(old.getNo());
    m.setCreatedDate(old.getCreatedDate());
    m.setName(streamTool.promptString(String.format("이름(%s)? ", old.getName())));
    m.setTel(streamTool.promptString(String.format("전화(%s)? ", old.getTel())));
    m.setEmail(streamTool.promptString(String.format("이메일(%s)? ", old.getEmail())));
    m.setDegree(streamTool.promptInt(String.format(
        "1. 고졸\n2. 전문학사\n3. 학사\n4. 석사\n5. 박사\n0. 기타\n학위(%s)? ",
        getDegreeText(old.getDegree()))));
    m.setSchool(streamTool.promptString(String.format("학교(%s)? ", old.getSchool())));
    m.setMajor(streamTool.promptString(String.format("전공(%s)? ", old.getMajor())));
    m.setWage(streamTool.promptInt(String.format("강의료(시급)(%s)? ", old.getWage())));

    String str = streamTool.promptString("정말 변경하시겠습니까?(y/N) ");
    if (str.equalsIgnoreCase("Y")) {
      this.teacherDao.update(m);
      streamTool.println("변경했습니다.");
    } else {
      streamTool.println("변경 취소했습니다.");
    }
    streamTool.send();
  }

  private void deleteTeacher(StreamTool streamTool) throws Exception {
    int teacherNo = streamTool.promptInt("강사번호? ");

    Teacher m = this.teacherDao.findByNo(teacherNo);

    if (m == null) {
      streamTool.println("해당 번호의 강사가 없습니다.").send();
      return;
    }

    String str = streamTool.promptString("정말 삭제하시겠습니까?(y/N) ");
    if (!str.equalsIgnoreCase("Y")) {
      streamTool.println("삭제 취소했습니다.").send();
      return;
    }

    teacherDao.delete(m);

    streamTool.println("삭제했습니다.").send();

  }

  private static String getDegreeText(int degree) {
    switch (degree) {
      case 1: return "고졸";
      case 2: return "전문학사";
      case 3: return "학사";
      case 4: return "석사";
      case 5: return "박사";
      default: return "기타";
    }
  }

  public void service(StreamTool streamTool) throws Exception {

    menu(streamTool);

    while (true) {

      String command = streamTool.readString();

      if (command.equals("menu")) {
        menu(streamTool);
        continue;
      }

      int menuNo;
      try {
        menuNo = Integer.parseInt(command);
      } catch (Exception e) {
        streamTool.println("메뉴 번호가 옳지 않습니다!").println().send();
        continue;
      }

      try {
        switch (menuNo) {
          case 0:
            streamTool.println("메인화면으로 이동!").send();
            return;
          case 1: this.inputTeacher(streamTool); break;
          case 2: this.printTeachers(streamTool); break;
          case 3: this.printTeacher(streamTool); break;
          case 4: this.modifyTeacher(streamTool); break;
          case 5: this.deleteTeacher(streamTool); break;
          default:
            streamTool.println("잘못된 메뉴 번호 입니다.");
        }
      } catch (Exception e) {
        streamTool.printf("명령 실행 중 오류 발생! - %s : %s\n",
            e.getMessage(),
            e.getClass().getSimpleName()).send();
      }
    }
  }

  void menu(StreamTool streamTool) throws Exception {
    streamTool.printf("[%s]\n", this.title)
    .println("1. 등록")
    .println("2. 목록")
    .println("3. 조회")
    .println("4. 변경")
    .println("5. 삭제")
    .println("0. 이전")
    .send();
  }
}

 

public class StudentHandler {

  private StudentDao memberDao;
  private String title;

  public StudentHandler(String title, StudentDao memberDao) {
    this.title = title;
    this.memberDao = memberDao;
  }

  private void inputMember(StreamTool streamTool) throws Exception {
    Student m = new Student();
    m.setName(streamTool.promptString("이름? "));
    m.setTel(streamTool.promptString("전화? "));
    m.setPostNo(streamTool.promptString("우편번호? "));
    m.setBasicAddress(streamTool.promptString("주소1? "));
    m.setDetailAddress(streamTool.promptString("주소2? "));
    m.setWorking(streamTool.promptInt("0. 미취업\n1. 재직중\n재직자? ") == 1);
    m.setGender(streamTool.promptInt("0. 남자\n1. 여자\n성별? ") == 0 ? 'M' : 'W');
    m.setLevel((byte) streamTool.promptInt("0. 비전공자\n1. 준전공자\n2. 전공자\n전공? "));

    this.memberDao.insert(m);

    streamTool.println("입력했습니다!").send();
  }

  private void printMembers(StreamTool streamTool) throws Exception {
    Student[] members = this.memberDao.findAll();
    streamTool.println("번호\t이름\t전화\t재직\t전공");
    for (Student m : members) {
      streamTool.printf("%d\t%s\t%s\t%s\t%s\n",
          m.getNo(), m.getName(), m.getTel(),
          m.isWorking() ? "예" : "아니오",
              getLevelText(m.getLevel()));
    }
    streamTool.send();
  }

  private void printMember(StreamTool streamTool) throws Exception {
    int memberNo = streamTool.promptInt("회원번호? ");

    Student m = this.memberDao.findByNo(memberNo);

    streamTool
    .printf("    이름: %s\n", m.getName())
    .printf("    전화: %s\n", m.getTel())
    .printf("우편번호: %s\n", m.getPostNo())
    .printf("기본주소: %s\n", m.getBasicAddress())
    .printf("상세주소: %s\n", m.getDetailAddress())
    .printf("재직여부: %s\n", m.isWorking() ? "예" : "아니오")
    .printf("    성별: %s\n", m.getGender() == 'M' ? "남자" : "여자")
    .printf("    전공: %s\n", getLevelText(m.getLevel()))
    .printf("  등록일: %s\n", m.getCreatedDate())
    .send();
  }

  // 인스턴스 멤버(필드나 메서드)를 사용하지 않기 때문에
  // 그냥 스태틱 메서드로 두어라!
  private static String getLevelText(int level) {
    switch (level) {
      case 0: return "비전공자";
      case 1: return "준전공자";
      default: return "전공자";
    }
  }

  private void modifyMember(StreamTool streamTool) throws Exception {
    int memberNo = streamTool.promptInt("회원번호? ");

    Student old = this.memberDao.findByNo(memberNo);

    if (old == null) {
      streamTool.println("해당 번호의 회원이 없습니다.").send();
      return;
    }

    // 변경할 데이터를 저장할 인스턴스 준비
    Student m = new Student();
    m.setNo(old.getNo());
    m.setCreatedDate(old.getCreatedDate());
    m.setName(streamTool.promptString(String.format("이름(%s)? ", old.getName())));
    m.setTel(streamTool.promptString(String.format("전화(%s)? ", old.getTel())));
    m.setPostNo(streamTool.promptString(String.format("우편번호(%s)? ", old.getPostNo())));
    m.setBasicAddress(streamTool.promptString(String.format("기본주소(%s)? ", old.getBasicAddress())));
    m.setDetailAddress(streamTool.promptString(String.format("상세주소(%s)? ", old.getDetailAddress())));
    m.setWorking(streamTool.promptInt(String.format(
        "0. 미취업\n1. 재직중\n재직여부(%s)? ",
        old.isWorking() ? "재직중" : "미취업")) == 1);
    m.setGender(streamTool.promptInt(String.format(
        "0. 남자\n1. 여자\n성별(%s)? ",
        old.getGender() == 'M' ? "남자" : "여자")) == 0 ? 'M' : 'W');
    m.setLevel((byte) streamTool.promptInt(String.format(
        "0. 비전공자\n1. 준전공자\n2. 전공자\n전공(%s)? ",
        getLevelText(old.getLevel()))));

    String str = streamTool.promptString("정말 변경하시겠습니까?(y/N) ");
    if (str.equalsIgnoreCase("Y")) {
      this.memberDao.update(m);
      streamTool.println("변경했습니다.");
    } else {
      streamTool.println("변경 취소했습니다.");
    }
    streamTool.send();
  }

  private void deleteMember(StreamTool streamTool) throws Exception {
    int memberNo = streamTool.promptInt("회원번호? ");

    Student m = this.memberDao.findByNo(memberNo);

    if (m == null) {
      streamTool.println("해당 번호의 회원이 없습니다.").send();
      return;
    }

    String str = streamTool.promptString("정말 삭제하시겠습니까?(y/N) ");
    if (!str.equalsIgnoreCase("Y")) {
      streamTool.println("삭제 취소했습니다.").send();
      return;
    }

    memberDao.delete(m);

    streamTool.println("삭제했습니다.").send();
  }

  private void searchMember(StreamTool streamTool) throws Exception {

    String keyword = streamTool.promptString("검색어? ");

    Student[] members = this.memberDao.findByKeyword(keyword);

    streamTool.println("번호\t이름\t전화\t재직\t전공");
    for (Student m : members) {
      streamTool.printf("%d\t%s\t%s\t%s\t%s\n",
          m.getNo(), m.getName(), m.getTel(),
          m.isWorking() ? "예" : "아니오",
              getLevelText(m.getLevel()));
    }
    streamTool.send();
  }

  public void service(StreamTool streamTool) throws Exception {

    menu(streamTool);

    while (true) {

      String command = streamTool.readString();

      if (command.equals("menu")) {
        menu(streamTool);
        continue;
      }

      int menuNo;
      try {
        menuNo = Integer.parseInt(command);
      } catch (Exception e) {
        streamTool.println("메뉴 번호가 옳지 않습니다!").println().send();
        continue;
      }

      try {
        switch (menuNo) {
          case 0:
            streamTool.println("메인화면으로 이동!").send();
            return;
          case 1: this.inputMember(streamTool); break;
          case 2: this.printMembers(streamTool); break;
          case 3: this.printMember(streamTool); break;
          case 4: this.modifyMember(streamTool); break;
          case 5: this.deleteMember(streamTool); break;
          case 6: this.searchMember(streamTool); break;
          default:
            streamTool.println("잘못된 메뉴 번호 입니다.").send();
        }
      } catch (Exception e) {
        streamTool.printf("명령 실행 중 오류 발생! - %s : %s\n",
            e.getMessage(),
            e.getClass().getSimpleName()).send();
      }
    }

  }

  void menu(StreamTool streamTool) throws Exception {
    streamTool.printf("[%s]\n", this.title)
    .println("1. 등록")
    .println("2. 목록")
    .println("3. 조회")
    .println("4. 변경")
    .println("5. 삭제")
    .println("6. 검색")
    .println("0. 이전")
    .send();
  }
}

 

 

 


 

조언

 

*

 

 


 

과제

 

/