본문 바로가기
Team Project (국비)/Team Project

6월 19일 프로젝트 Model 파트

by Hwanii_ 2023. 6. 24.
728x90

1.

크롤링 해온 책의 데이터들을 BookDAO 에서 insert 메서드를 통해서 DB에 삽입 하기.

 

 

 

JDBCUtil 클래스에서 connect() 메서드를 통해서,

connetion 객체의 정보를 conn 참조변수에 저장 한다.

 

비즈니스 메서드인 insert 메서드는

Controller로부터 BookVO 타입의 bVO

라는 매개변수로 객체를 인자로 받는다.

 

향상된 statement 객체를 통해서, sql 구문을 인자로 넣을 수 있다.

 

set 할 수 있는 메서드를 지니고 있기에,

 

책의 제목, 가격, 개수, 카테고리 정보 4가지를 객체로부터 get 해서

sql 구문의 값에 set 해준다.

 

sql 구문은 아래와 같다.

 

 

BOOK 이라는 이름을 가진 테이블에 INSERT  할거야.

 

칼럼명은 각각 TITLE, PRICE, CNT, CATEGORY 이고,

 

각 칼럼에다가 ? 값을 밀어 넣을 거야.

 

? 에 해당하는 값을 바로 44번째 라인 부터 48번째 라인의 set 메서드를 통해서 값을 밀어 넣는다.

 

51번째 라인 >>

sql 구문을 통해, DB에 데이터를 insert 했을때, 그 결과값을 int 타입의 변수 result에 받는다.

 

pstmt.executeUpdate() 는 결과값을 숫자로 주게 된다.

 

result가 0보다 작거나 같으면, 해당 테이블에 데이터가 밀어넣어지지 않았다는 것을 의미 한다.

그래서 return 값으로 false를 주는식으로 코드를 구성하면,

Controller 에서 결과값을 받았을 때 false 이면,

'값이 잘 밀어 넣어 지지 않았습니다' 라는 식의 멘트를 출력 시킬 수 있게 된다.

 

if문도 통과하고, catch문도 통과하고, finally문도 무사히 통과하면,

데이터를 잘 삽입했다는 의미이니, return 값으로 true를 반환하게 된다.

 

2.

사용자가 책을 검색 하고 싶은 상황.

 

C가 M에게 사용자가 책 검색을 원한다고 말한다.

M은 해당 기능을 잘 수행하고, 결과값을 C에게 보내준다.

C는 결과값을 잘 받아서, V에게 결과값을 보낸다.

V는 C에게 결과값을 받고, 책 검색 결과를 사용자에게 보여주게 된다.

 

책 검색 기능은

이름으로 검색,

필터검색,

최저가 검색,

최고가 검색

총 4가지의 기능으로 구현 했다.

 

이름검색, 필터검색, 최저가 검색, 최고가 검색

모두 BookDAO의 selectAll() 메서드에 해당 하게 된다.

(한개만 콕 집어서 그것만 검색 할 수 있는 상황이 아니니까 selectAll() 이다.)

 

 

selectAll() 메서드는 return 값으로 ArrayList<BookVO> 를 반환 해야 하는 상황 이므로,

72번째 라인 처럼 배열리스트를 생성 한다.

 

77번째 라인 ~ 91번째 라인 >>

 

C에서 객체의 값으로 보내준 SearchKeyWord 가

"이름검색" 이랑 같아 ?

"필터검색" 이랑 같아 ?

"최저가" 이랑 같아 ?

"최고가" 이랑 같아 ?

 

그러면 각각 if - else if 문이 실행 되는 구조이다.

 

이름 검색은 책의 이름에 대한 정보가 있어야 검색이 가능하고,

필터 검색은 책의 가격에 대한 정보가 있어야 검색이 가능하다.

 

최저가랑, 최고가는 특별히 책에 대한 정보가 있지 않아도,

DB 내부에 책에 가격에 대해 최저가 또는 최고가를 판단하여,

결과값을 보내줄 수 있다. (sql 구문을 통해서)

 

77번째 라인의 변수명, 79번째 라인의 변수명과, 83번째 라인의 변수명들은

 

기존 BookVO의 멤버변수가 아니라,

값을 새롭게 set 해주기 위해서 만들어 놓는 임시변수의 개념이다.

값을 변경하거나 하는 경우에만 사용되는 (그러한 목적으로 만들어진 변수) 이러한 임시변수들은

당연하게도 생성자를 통해 값을 초기화 할 필요가 없는 개념 이다.

 

VO 클래스를 확인 하면 아래와 같다.

 

다음부터는 변수명을 카멜표기법으로 잘 작성하기.

 

4번 부터 8번 라인까지는 멤버변수 이고,

 

10번 부터 16번 라인까지는 값을 새롭게 set 하기 위한 용도로 만들어진 임시 변수 이다.

 

 각각의 쿼리문은 아래와 같다.

 

 

이름 검색은 JAVA의 contain() 메서드 처럼 , LIKE CONCAT 구문으로 이름 검색이 가능 하다.

 

필터검색은 사용자로부터 최저값, 최고값을 받아서 각각의 값들을 sql 구문의 ? 부분에 set 한다.

 

최저가, 최고가 검색은

MIN(PRICE), MAX(PRICE) 함수 덕분에  sql 구문으로 쉽게 해당 기능들을 구현할 수 있다.

 

 

CRUD 메서드 에서, Read에 해당하는 selectAll() 또는, selectOne() 은

pstmt.excuteQuery() 메서드를 사용 해야 한다.

해당 결과값은, 반드시 ResultSet 객체를 통해 받게 된다.

 

예) ResultSet rs = null; 또는 ResultSet rs; 로 선언 후

 

rs = pstmt.executeQuery();

 

해서 결과값을 rs 참조변수에 저장 했으니,

 

next() 메서드를 통해서 로직을 구현 해야 한다.

 

얻어온 결과값이 총 몇개인지 모르니까 몇번 반복해야할지 모른다.

그래서 while문을 사용 한다. (어감상)

 

BookVO 타입의 bdata 참조변수로 새롭게 객체를 생성 한다.

 

각각

"NUM" 이라는 칼럼명을 가졌는데,해당 열이 int 타입이야 ?

그러면 그 값을 가져오라는 의미 이다.

 

"TITLE" 이라는 칼럼명을 가졌는데,해당 열이 String 타입이야 ?

그러면 그 값을 가져오라는 의미 이다.

 

"PRICE" 이라는 칼럼명을 가졌는데,해당 열이 int 타입이야 ?

그러면 그 값을 가져오라는 의미 이다.

 

"CNT" 이라는 칼럼명을 가졌는데,해당 열이 int 타입이야 ?

그러면 그 값을 가져오라는 의미 이다.

 

"B.CATEGORY" 이라는 칼럼명을 가졌는데,해당 열이 int 타입이야 ?

그러면 그 값을 가져오라는 의미 이다.

 

그렇게 객체의 인자 값을 모두 get 하고,

그 값의 정보들이 담긴 bdata 객체를

배열리스트에 저장 한다. >> 배열리스트를 통해 return 하는 상황이니까.

 

>> bdatas.add(bdata);

 

 

해서 catch 구문 finally 구문까지 모두 통과하면

return 값으로 배열리스트 bdatas를 토해 내게 된다.

 

3.

 

 

C에게서

키워드 변수인 sk의 값을 "재고추가" 로 받은 경우랑

키워드 변수인 sk의 값을 "재고빼기" 로 받은 경우가 있다.

 

재고 추가는, 책의 재고 개수를 더하는 기능이고,

 

재고 빼기는 2가지 상황에 사용된다. (하는 기능이 똑같아서)

1)

사용자가 책을 구매했을 때 사용자가 구매하는 개수만큼

기존 재고에서 개수를 빼는 기능.

 

2)

책의 재고 개수를 빼는 기능.

 

tmpCnt는 V에서 사용자에게 입력받은 책의 개수를 임시로 저장할 임시 변수 이다.

tmpCnt의 값을 객체에 정보에 set 해서 값을 C가 M에게 보내주는 상황 이다.

 

 

UPDATE BOOK SET CNT = CNT + 기존 책 재고에 더할 개수 WHERE NUM = 책번호 ;

 

UPDATE BOOK SET CNT = CNT - 기존 책 재고에 뺄 개수 WHERE NUM = 책번호 ;

 

UPDATE BOOK SET CNT = CNT - 책을 구매할 개수 WHERE NUM = 책번호 ;

 

4.

카트에 사용자가 고른 책을 담는 상황.

 

카트는 DBMS를 이용해서, 테이블을 만들어 놓은 상황.

 

장바구니에 담는 개념이라 insert() 메서드에 해당한다.

 

 

sql 구문을 prepareStatement() 메서드의 인자로 넣는다.

sql 구문에 있는 ? 부분에 값을 set 해준다.

 

 

midfk는 member의 id를 의미한다.

근데, cart 테이블에 외래키로 사용이 되고 있어서,

변수명을 그냥 midfk 라고 지은 모습.

 

bnumfk는 book의 pk를 의미한다.

근데, cart 테이블에 외래키로 사용이 되고 있어서,

변수명을 그냥 bnumfk 라고 지은 모습.

 

 

cart 테이블의 열을 확인하면,

 

NUM, MIDFK, BNUMFK, CNT 4개가 있다.

 

NUM은 카트 테이블의 각 행에 대한 PK를 의미하는 열이고,

 

MIDFK는 멤버 테이블의 ID 열을 외래키로 사용한것을 의미.

 

BNUMFK는 북 테이블의 책 PK를 외래키로 사용한것을 의미.

 

CNT는 카트 테이블에서 카트에 담은 각 책의 개수를 의미.

 

 

굉장히 간단한 sql 구문을 확인할 수 있다.

 

CART 테이블에 3개의 열에 각각의 값들을 set 해서 데이터를 밀어 넣어주는 것이다.

 

5.

회원의 카트의 목록을 전체출력 하고 싶은 상황.

 

전체출력이니, selectAll() 메서드에 해당 한다.

 

return 값으로 CartVO 타입의 배열리스트를 토해내야 하는 메서드 이니까,

 

DB에서 가져온 데이터를 배열리스트에 add() 해서 그 배열리스트를 return 해줘야 한다.

 

 

76번째 라인을 보면,

카트에 담을 cdata 객체를 새롭게 new 키워드를 통해 만드는 모습을 볼 수 있다.

객체의 정보로는, 즉, 카트에 담을 책의 정보로는, CartVO의 멤버변수로 선언해준 4개만 있으면 된다.

 

 

 

sql문은 위와 같다.

 

ROW_NUMBER() >>

OVER >>

C.NUM >>

B.MIDFK >>

C.BNUMFK >>

..

ORDER BY C.NUM >>

JOIN >>

 

 

CartVO를 보면, tmpRowNum 하고 tmpTitle 하고 tmpPrice를 사용해서 toString 한것을 볼 수 있다.

 

★ [ 다시 정리 하기 ] ★

 

1) 저 임시 변수들을 사용한 의도가 뭔지

2) selectAll() 메서드 에서, cdata 객체에 임시 변수 3개를 set 해주는 모습을 볼 수 있는데,

그 부분 뭔지

3) sql 구문 뭔지

( member 테이블의 id에 해당하는 fk만 set 해주면 되는 상황인데.. )

 

6.

사용자가 책을 구매했을 때,

구매할 책의 번호를 선택하고, 있으면 OK. 없으면 구매 실패 이다.

유효한 책의 번호라면,

해당 책을 몇권 살건지를 사용자에게 입력 받는다.

책의 재고가 사용자가 구매할 책의 개수보다 많거나 같으면 OK. 적으면 구매 실패 이다.

 

이때, 책을 바로 구매할건지, 카트에 담을건지 선택할 수 있고,

카트에 담을거라면, 

DB의 카트 테이블로 들어가야하는 정보는,

테이블은 회원마다의 테이블 이니까,

회원의 id 정보, 책의 번호 (어떤 책인지 식별이 되야하니까), 해당 책을 몇권 담을건지 개수

이렇게 3가지 이다.

 

 

C에서 위와같이 3가지 정보를 객체 묶음으로 해서,

 

 

cartDAO.selectOne(cVO)가 != null 인 경우와,

cartDAO.selectOne(cVO)가 == null 인 경우로

 

나뉘게 된다.

 

이게 뭐냐면,

기존 장바구니에 지금 담으려고 하는 책이 이미 있으면,

!= null 인데,

그런 경우에는 bookCnt만 올리면 된다.

 

기존 장바구니에 지금 담으려고 하는 책이 없으면,

== null 이라

이런 경우에는 정보가 담겨있는 객체 묶음 cVO 를 insert() 메서드의 인자로 보내서

장바구니에 새로운 책을 담게 되는 로직 이다.

 

아래는 CartDAO의 selectOne() 메서드 이다.

 

 

 

 

C에서 selectOne 해서 null이 아니면, 이미 장바구니에 있다는 의미니까

다시 cVO 객체를 selectOne 한것과 cnt를 set 해서

cartDAO의 update() 메서드의 인자로 주면 된다.

 

sql문 >>

쿼리문의

MIDFK 는 C에서 넘겨준 회원의 아이디 정보이고

BNUMFK 는 C에서 넘겨준 책의 번호를 의미 한다.

 

 

 

WHERE NUM 은 caVO.getNum()으로 set 해주는 상황인데,

caVO.getNum()은,  0 고정값 아닌가..?

CartVO를 보면 생성자 3개짜리 (string int int) 객체 들어오면,

 

 

위와 같이 되어있는데, this.num = 0 아닌지..

 

잘 밀어 넣어지네..?

 

★ 위에 부분도 다시 정리 하기 ★

 

 

 

카트에 담으려고 하는 책이 없으면 insert() 이다.

 

 

7.

 

 

 

카트에 담겨져 있는 책을 1개 지정해서 삭제하거나, 또는 전체를 삭제하는 기능.

 

전체삭제는 회원의 pk를 의미하는 MIDFK를 객체에서 get 해서 ? 부분에 값을 set 해주면

조건에 맞는 회원의 행을 전부 삭제.

 

한권삭제는 회원의 MIDFK와 어떤 책을 삭제할건지 BNUMFK를 받아서

조건에 맞는 행 1개를 삭제.

 

 

이렇게 test02 라는 회원이 3개를 장바구니에 갖고 있으면,

 

이클립스에서는 이렇게 보여지고 있다.

 

 

사용자가 1번 책을 삭제시, 1번책이 삭제 된다.

 

 

 

전체 삭제시, 모두 삭제.

 

 

 

8.

 

사용자가 카테고리에 따른 책 추천을 받고 싶은 상황일 때, 구현한 기능.

 

 

카테고리 배열리스트를 만들어 주기.

왜냐하면, 카테고리 리스트를 selectAll() 해서 배열리스트 자체를 C가 받아서

V에게 보내줘야 V가 사용자에게 카테고리 목록을 출력해 줄 수 있으니까..

 

 

 

CategoryDAO의 selectAll() 메서드 이다.

 

sql 구문은 아래와 같고,

 

rs.next()를 통해 cdatas 배열리스트에 카테고리 (객체)가 하나씩 차례대로 add() 된다.

 

 

 

그리고, 해당 DAO에서는 selectAll() 메서드만 사용되는 상황인데,

 

사용하지 않는 메서드들은 맨앞에 private 처리를 해서, 외부에서 접근이 안되도록 하면

C에서 코드를 짤때, 실수하지 않게 할 수 있다.

 

예시

 

 

 

 

반응형