TIL2 - (JDBC) crud 콘솔로 구현해보기(2) (UI, 첫페이지, 끝페이지 구현)

김지인·2022년 7월 5일
0
post-thumbnail

지난번에 리스트를 콘솔에 출력하는 과정을 끝냈다.
이번에는 UI와 첫페이지, 끝페이지를 표시해보자.


사용자와 상호작용하는 메뉴 UI 구현

보통 게시판을 생각해보자.

이전페이지, 다음페이지, 검색 등등을 할 수 있지 않은가?

그러면 우선적으로 사용자가 선택할 수 있도록 메뉴 UI를 구현해보겠다.

public class membermain {

	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		MemberConsole mc = new MemberConsole();
		mc.printMemberList();
		
		mc.printMenuList(); // 추가 
	}
}

실행하는 membermainprintMenuList()를 실행하여 리스트와 같이 나오게 해보자.

	public int printMenuList() {
		System.out.print("/ 1. 이전페이지 / 2. 다음페이지 / 3. 검색 / 4. 종료 />");
		//사용자와 상호작용 하기 위한 출력안내문
		Scanner sc = new Scanner(System.in);
		String choice_ = sc.nextLine();
		//데이터를 입력받는 로직, 숫자외 다른 문자가 입력을 받을 수도 있으니 nextLine()으로 데이터 받음.
		int choice = Integer.parseInt(choice_);
		//입력받은 String형을 int형으로 변환하여 입력이 가능하게끔 함
		
		return choice;
		//입력받은 숫자를 아웃함.
	}

MemberConSole에서 구현한 printMenuList()로직.


public static void main(String[] args) throws ClassNotFoundException, SQLException {
		MemberConsole mc = new MemberConsole();
		
		EXIT:
		while(true) { //명령어를 입력했을 때 다시 콘솔창에 출력되기 위해 while문으로 계속출력.
			mc.printMemberList();
			
			int choice = mc.printMenuList();
			switch(choice) { //printMenuList로부터 받은 choice번호를 구분하여 명령을 실행하는 switch문
			case 1: // 이전페이지를 명령하는 숫자
				break;
			case 2: // 다음페이지를 명령하는 숫자
				break;
			case 3: // 검색을 명령하는 숫자
				break;
			case 4: // 종료를 명령하는 숫자
				System.out.println("----------------");
				System.out.println("종료 합니다.");
				System.out.println("----------------");
				break EXIT; // while문에 EXIT를 달아 반복문을 빠져나옴. 
			default: // 다른 숫자를 입력했을때.
				System.out.println("잘못 입력하셧습니다.");
				break;
			}	
		
		}
	}
//출력결과
-----------------------------------------------
ID: bmm522, PWD: 1234, NAME: 김지인
ID: rlawldls11, PWD: 4567, NAME: 김성필
ID: rerere, PWD: 244443, NAME: 로버트
ID: asdfsdf, PWD: 1234, NAME: 홍록기
ID: asdad, PWD: 1244, NAME: 강동원
ID: SASD, PWD: 1234, NAME: ㅇㄻㄴ
ID: asfsdf, PWD: 2322, NAME: 김김김
-----------------------------------------------
/ 1. 이전페이지 / 2. 다음페이지 / 3. 검색 / 4. 종료 />
  • while(true)를 돌리면서 사용자가 종료버튼을 누르기 전까지 계속 실행되도록 한다.
  • 사용자가 명령하는 숫자를 switch문으로 두어 각각의 케이스에 맞게 실행되도록 설계.
  • 혹여나 다른 번호를 입력할수도 있으니 default를 두어 잘못입력을 알림.
  • 프로그램의 종료를 위해 while문에 EXIT을 달아 반복문을 나올 수 있도록 함.

페이지 단위로 뷰를 나누기

하나의 페이지에 몇개의 결과를 보여줄까?

하나의 페이지에 "3"개씩 리스트를 보여준다고 가정하자.

그렇다면 기존의 쿼리문을 수정해보자.

memberservice클래스의 getMember()의 sql문을 가져와봣다.

String sql = "SELECT * FROM MEMBER";


그리고 테이블이랑 같이 보면 UNIQUENUMBER이 시퀀스 넘버이기때문에 이것을 이용하여
SQL구문을 수정해보자.

String sql = "SELECT * FROM MEMBER WHERE UNIQUENUMBER ? AND ?";

다음과 같이 ?안에 숫자를 넣어 해당하는 UNIQUENUMBER의 값의 데이터만 뽑아 올 수 있는 쿼리문이 완성 되었다.

그렇다면 ?안에 들어갈 숫자는 어떻게 설정할까?

public List<member> getMember(int checknumber) throws ClassNotFoundException, SQLException{
		int startUniqueNumber = 1+(checknumber-1)*3; //1, 4, 7, 10 ... 으로 가는 식
		int endUniqueNumber = checknumber*3;//3, 6, 9, 12 ... 으로가는 식
		String sql = "SELECT * FROM MEMBER WHERE UNIQUENUMBER BETWEEN ? AND ?";
		
		Class.forName(driver);
		Connection con = DriverManager.getConnection(url, uid, upwd);
		PreparedStatement st = con.prepareStatement(sql); // sql 구문에 값을 꽂아 넣기 위한 준비
		
		st.setInt(1, startUniqueNumber); // 첫번째 ?의 값에 꽂아 넣기
		st.setInt(2, endUniqueNumber); // 두번째 ?의 값에 꽂아 넣기
		
		ResultSet rs = st.executeQuery(); // 꽂아진 데이터를 사용하기 위해 ResultSet객체에 담기
		
		List<member> list = new ArrayList<member>(); //각자 테이블에서 추출한 값을 담아줄 리스트
		while(rs.next()) { //테이블의 마지막까지 탐색
			String id = rs.getString("ID");
			String pwd = rs.getString("PWD");
			String name = rs.getString("NAME");
			int uniquenumber = rs.getInt("UNIQUENUMBER");
// ------------------여기까지 추출을 하고--------------------------
			
			member member = new member(id, pwd, name, uniquenumber); // member에 추출한 값 담기
			list.add(member); //담은 값을 리스트에 담기
		}

getMember()의 메서드에 checknumber를 꽂으면 시작하고 끝나는 UNIQUENUMBER를 구하는 로직을 구현하여 그 값을 sql구문에 꽂아 넣을 수 있게끔 수정한다.

  • checknumber은 보여지고 싶은 첫 데이터의 UNIQUENUMBER를 설정
  • ?값에 꽂아 넣을 startUniqueNumberendUniqueNumberchecknumber를 이용해 설정.
  • 따라서 해당 메서드는 3개의 데이터만 가져오는 로직으로 수정.

이번에는 getMember()에 꽂아넣은 checknumber를 설정하고 콘솔에서 구현해보자.
그리고 추가로 현재 페이지를 알려주는 프린트문을 추가하자.

public class MemberConsole {
	
	private memberservice ms; 
	
	private int checknumber; //추가
	
	public MemberConsole() {
		ms = new memberservice();
		checknumber = 1; //첫번째 데이터부터 출력하기 위해 1로 설정
		
	}
	
	public void printMemberList() throws ClassNotFoundException, SQLException {
		List<member> list = ms.getMember(checknumber); 
		// memberservice.getMember에서 아웃된 리스트를 담을 리스트 
        // checknumber을 1로 설정하고 넣음으로써 첫번째부터 3개씩 출력
		
		System.out.println("-----------------------------------------------");
		list.forEach(m -> System.out.printf("ID: %s, PWD: %s, NAME: %s\n", m.getId(), m.getPwd(), m.getName()));
		System.out.println("-----------------------------------------------");
		System.out.println("           현재페이지 / 끝페이지"); 
        //추가적으로 데이터가 몇페이지에 있는지 알려주는 프린트 문을 추가 (추후 기능을 구현)
	}

	public int printMenuList() {
		System.out.print("/ 1. 이전페이지 / 2. 다음페이지 / 3. 검색 / 4. 종료 />");
		//사용자와 상호작용 하기 위한 출력안내문
		Scanner sc = new Scanner(System.in);
		String choice_ = sc.nextLine();
		//데이터를 입력받는 로직, 숫자외 다른 문자가 입력을 받을 수도 있으니 nextLine()으로 데이터 받음.
		int choice = Integer.parseInt(choice_);
		//입력받은 String형을 int형으로 변환하여 입력이 가능하게끔 함
		
		return choice;
		//입력받은 숫자를 아웃함.
	}
}
public class membermain {

	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		MemberConsole mc = new MemberConsole();
		
		EXIT:
		while(true) { //명령어를 입력했을 때 다시 콘솔창에 출력되기 위해 while문으로 계속출력.
			mc.printMemberList();
			
			int choice = mc.printMenuList();
			switch(choice) { //printMenuList로부터 받은 choice번호를 구분하여 명령을 실행하는 switch문
			case 1: // 이전페이지를 명령하는 숫자
				break;
			case 2: // 다음페이지를 명령하는 숫자
				break;
			case 3: // 검색을 명령하는 숫자
				break;
			case 4: // 종료를 명령하는 숫자
				System.out.println("----------------");
				System.out.println("종료 합니다.");
				System.out.println("----------------");
				break EXIT; // while문에 EXIT를 달아 반복문을 빠져나옴. 
			default: // 다른 숫자를 입력했을때.
				System.out.println("잘못 입력하셧습니다.");
				break;
			}	
		
		}
	}

}
//출력결과
-----------------------------------------------
ID: bmm522, PWD: 1234, NAME: 김지인
ID: rlawldls11, PWD: 4567, NAME: 김성필
ID: rerere, PWD: 244443, NAME: 로버트
-----------------------------------------------
           현재페이지 / 끝페이지
/ 1. 이전페이지 / 2. 다음페이지 / 3. 검색 / 4. 종료 />

페이지 처음과 끝 표시와 페이지 이동기능 구현

첫페이지와 마지막페이지를 구해보자.

memberservice클래스의 getMember메서드를 다시보자.

public List<member> getMember(int checknumber) throws ClassNotFoundException, SQLException{
		int startUniqueNumber = 1+(checknumber-1)*3; //1, 4, 7, 10 ... 으로 가는 식
		int endUniqueNumber = checknumber*3;//3, 6, 9, 12 ... 으로가는 식

getMember의 일부분을 가져와봣다. 만약에 checknumber에 2를 넣으면 출력되는 데이터는 어떻게 될까?

리스트는 4번째부터 6번째까지의 데이터를 보여줄 것이다.

3을 넣으면? 7번째부터 9번째의 데이터를 보여줄 것이다.

따라서 저 checknumber로 현재 페이지를 표시할 수 있다.
또한 페이지의 끝을 나타내는 endPageNumber도 만들어보자.

public class MemberConsole{
	.
    .
    public void printMemberList() throws ClassNotFoundException, SQLException {
    	int endPageNumber;
        .
        .
        //System.out.println("           현재페이지 / 끝페이지");
        System.out.printf("            %d / %d\n", checknumber, endPageNumber);
    }
}

우선적으로 실행되는 도중에 글이 업데이트 되거나 삭제될 수 있기 때문에 endPageNumber을 지역변수로 선언하고 끝페이지에 해당하는 위치에 넣었다. 근데 endPageNumber을 어떻게 만들까?


생각을 해보자.

우리는 지금 3개씩 출력하는 리스트 화면을 만들었다. 그렇다면 데이터의 총 갯수에서 3개를 나누고 그 몫이 마지막페이지가 아닐까?

그런데 생각해야할게 있다.

현재 데이터는 7개가있다. 근데 만약에 위와 같이 하면 끝페이지는 2가 될것이다. 그러므로 만약에 3으로 나눳을때 나머지가 있는경우는 +1을 해줘야 마지막페이지가 정확하게 나올 것이다.

또한 전체 데이터의 갯수를 알 수 있다면 콘솔창에 총 갯수도 출력가능하다.

```java
public class MemberConsole{
	.
    .
    public void printMemberList() throws ClassNotFoundException, SQLException {
    	int totaldata = ms.getTotal(); // 전체데이터값을 가져오는 메서드
       
       int endPageNumber = totaldata/3; ////전체 데이터에서 3으로 나눈 값을 넣어줌.
		
        if(totaldata%3 !=0) { //3으로 나눈값이 나머지가 있을 경우에 endPageNumber에 1을 추가
			endPageNumber ++;
		}
        .
        .
        System.out.printf("등록된 총 ID : %d\n", totaldata);// 프린트문 추가
        .
        .
      }
 }
  • memberservice클래스에서 getTotal()이라는 함수를 호출하면 전체데이터의 수를 가져옴.
  • getTotal()에서 가져온 값을 totaldata에 담아줌
  • 해당로직에 출력되는 리스트의 개수를 나눈후 나머지 검사후 끝페이지 표시.
  • totaldata의 값은 실행되는 동시에 바뀔 수 있으므로 지역변수로 선언.

그 다음으로는 getTotal()을 구현해보자

	public int getTotal() throws ClassNotFoundException, SQLException {
		int totaldatacount = 0; // 데이터의 총 갯수를 담기위한 변수 선언
		
		String sql = "SELECT COUNT(UNIQUENUMBER) FROM MEMBER";
		//UNIQUENUMBER는 데이터의 갯수만큼 생성되기 때문에 UNIQUENUMBER을 카운트함.
		
		Class.forName(driver);
		Connection con = DriverManager.getConnection(url, uid, upwd);
		Statement st = con.createStatement();
		ResultSet rs = st.executeQuery(sql);//그 값을 객체에 담기 위해 사용
		
		rs.next(); //열이 하나밖에 없기때문에 한번만 탐색해도 괜찮음.
		
		totaldatacount=rs.getInt("COUNT(UNIQUENUMBER)"); 
		// 총 갯수의 값을 totaldatacount값에 담음.
		
		return totaldatacount;
        
        rs.close();
        st.close();
        con.close();
        
	}
  • 데이터의 총 갯수를 담을 변수인 totaldatacount선언.
  • UNIQUENUMBER은 총 갯수만큼 생성되므로 UNIQUENUMBER의 갯수를 세는 SQL구문 작성.


해당 SQL구문 실행결과

  • 한번만 탐색하면 되므로 rs.next() 선언
  • 값을 가져와서 그 값을 totaldatacount에 담고 아웃

public class membermain {

	public static void main(String[] args)
    throws ClassNotFoundException, SQLException {
    }
}
//출력결과
-----------------------------------------------
ID: bmm522, PWD: 1234, NAME: 김지인
ID: rlawldls11, PWD: 4567, NAME: 김성필
ID: rerere, PWD: 244443, NAME: 로버트
-----------------------------------------------
                 1 / 3
/ 1. 이전페이지 / 2. 다음페이지 / 3. 검색 / 4. 종료 />

원하는대로 메뉴 UI와 첫페이지 끝페이지를 구성했다.
다음번에는 기능을 하나하나 구현해보자.

profile
에러가 세상에서 제일 좋아

0개의 댓글