2021. 12. 9. 14:48ㆍ스프링부트
지금까지 매장목록은 별점, 댓글 수, 가게 오픈상태가 주석처리 되어있었습니다
위 데이터를 불러오기 위해 storeList 쿼리를 수정합니다
<select id="storeList" resultType="Store">
WITH R_COUNT AS (
SELECT STORE_ID
,ROUND(AVG(SCORE), 1) SCORE
,COUNT(REVIEW_CONTENT) REVIEW_COUNT
,COUNT(BOSS_COMMENT) BOSS_COMMENT_COUNT
FROM BM_REVIEW
GROUP BY STORE_ID
),
STORE AS (
SELECT S.*,
T.*,
CASE WHEN MOD(24 - S.OPENING_TIME + S.CLOSING_TIME, 24) != 0 THEN MOD(24 - S.OPENING_TIME + S.CLOSING_TIME, 24) ELSE 24 END BS_TIME
FROM BM_STORE S
LEFT JOIN R_COUNT T
ON S.ID = T.STORE_ID
WHERE CATEGORY = #{category}
AND STORE_ADDRESS1 LIKE '${address1}%'
<if test="sort == '배달 빠른 순'">
ORDER BY DELEVERY_TIME
</if>
<if test="sort == '배달팁 낮은 순'">
ORDER BY DELEVERY_TIP
</if>
<if test="sort == '별점 높은 순'">
ORDER BY SCORE
</if>
<if test="sort == '리뷰 많은 순'">
ORDER BY REVIEW_COUNT
</if>
<if test="sort == '최소 주문 금액 순'">
ORDER BY MIN_DELEVERY
</if>
)
SELECT * FROM
(SELECT ROWNUM RN,
RESULT.*
FROM
(SELECT C.*
,'true' IS_OPEN
FROM STORE C
WHERE TO_CHAR(SYSTIMESTAMP, 'HH24') BETWEEN OPENING_TIME AND OPENING_TIME + BS_TIME
UNION ALL
SELECT C.*
,'false' IS_OPEN
FROM STORE C
WHERE TO_CHAR(SYSTIMESTAMP, 'HH24') NOT BETWEEN OPENING_TIME AND OPENING_TIME + BS_TIME
) RESULT
)
WHERE RN BETWEEN #{firstList } AND ${lastList }
</select>
갑자기 쿼리문이 길어졌는데 쿼리문 내의 중복을 제거하기위해 WITN문을 사용했습니다
WITH R_COUNT AS (
SELECT STORE_ID
,ROUND(AVG(SCORE), 1) SCORE
,COUNT(REVIEW_CONTENT) REVIEW_COUNT
,COUNT(BOSS_COMMENT) BOSS_COMMENT_COUNT
FROM BM_REVIEW
GROUP BY STORE_ID
),
WITH 문 안의 가게 점수,댓글 수 결과를 R_COUNT라는 이름을 붙이겠다는 의미 입니다
STORE AS (
SELECT S.*,
T.*,
CASE WHEN MOD(24 - S.OPENING_TIME + S.CLOSING_TIME, 24) != 0 THEN MOD(24 - S.OPENING_TIME + S.CLOSING_TIME, 24) ELSE 24 END BS_TIME
FROM BM_STORE S
LEFT JOIN R_COUNT T
ON S.ID = T.STORE_ID
WHERE CATEGORY = #{category}
AND STORE_ADDRESS1 LIKE '${address1}%'
위에서 R_COUNT로 이름붙인 테이블과 매장테이블을 조인해 카테고리와 주소에 맞는 모든 데이터를 가져와 STORE라고 이름을 붙입니다
CASE WHEN MOD(24 - S.OPENING_TIME + S.CLOSING_TIME, 24) != 0
THEN MOD(24 - S.OPENING_TIME + S.CLOSING_TIME, 24)
ELSE 24 END BS_TIME
영업시간이 0~24일 경우 계산값이 0이 되기 때문에 0일 경우엔 24로 변경해주었습니다
--(24 - 0 + 24) % 24
가게 정렬 버튼을 위해 IF문을 넣었고
<if test="sort == '배달 빠른 순'">
ORDER BY DELEVERY_TIME
</if>
<if test="sort == '배달팁 낮은 순'">
ORDER BY DELEVERY_TIP
</if>
<if test="sort == '별점 높은 순'">
ORDER BY SCORE
</if>
<if test="sort == '리뷰 많은 순'">
ORDER BY REVIEW_COUNT
</if>
<if test="sort == '최소 주문 금액 순'">
ORDER BY MIN_DELEVERY
</if>
현재시간이 영업 시작시간 + 위 테이블의 CASE결과값 사이에 있다면 'true'를 아니라면 'false'를 출력합니다
페이징을 위해 ROWNUM을 포함한 SELECT문으로 한번 더 감싸주었습니다
SELECT * FROM
(SELECT ROWNUM RN,
RESULT.*
FROM
(SELECT C.*
,'true' IS_OPEN
FROM STORE C
WHERE TO_CHAR(SYSTIMESTAMP, 'HH24') BETWEEN OPENING_TIME AND OPENING_TIME + BS_TIME
UNION ALL
SELECT C.*
,'false' IS_OPEN
FROM STORE C
WHERE TO_CHAR(SYSTIMESTAMP, 'HH24') NOT BETWEEN OPENING_TIME AND OPENING_TIME + BS_TIME
) RESULT
)
이제 store-li.jsp의 주석처리된 부분을 모두 해제합니다
update bm_store set opening_time = 23, closing_time = 00 where store_name = '피자헛';
COMMIT;
영업시간을 23~00시로 변경하고 매장목록을 확인해봅니다
페이징을 하기 위해 DB에 테스트용 데이터를 입력합니다
BEGIN
FOR I IN 1 .. 100 LOOP
INSERT INTO bm_store VALUES (STORE_ID_SEQ.NEXTVAL, 100, '테스트'
,'31099','천안시 두정동', '상세주소', '01013245678', '\img\none.gif', '\img\none.gif', 23, 00, 2000,30, 2000, '가게 소개 없음');
END LOOP;
END;
COMMIT 후 매장목록을 확인합니다
한번에 출력될 페이지를 조절하기 위해 쿼리를 추가합니다
WHERE RN BETWEEN 1 AND 10
store.js의 주석을 해제합니다
scroll() 함수를 이용해 스크롤이 바닥에 닿았을 때 다음페이지를 가져올 수 있게 구현했습니다
다음 페이지를 가져올 코드를 StoreController에 추가합니다
@ResponseBody
@GetMapping("/store/storeList")
public ResponseEntity<List<Store>> sortStore(int category, int address1, String sort, int page, Model model) {
List<Store> storeList = storeService.storeList(category, address1 / 100, sort, page);
return new ResponseEntity<>(storeList, HttpStatus.OK);
}
페이지를 관리할 Page클래스를 util패키지에 추가합니다
@Getter
@ToString
public class Page {
private int view = 10; // 화면에 출력할 목록 수
private int firstList; // 페이지 첫번째 목록
private int lastList; // 페이지 마지막 목록
public Page() {
this(1);
}
public Page(int movePage) {
page(movePage, view);
}
public Page(int movePage, int view) {
page(movePage, view);
}
public void page(int movePage, int view) {
this.firstList = (view * movePage) - view + 1;
this.lastList = movePage * view;
}
}
먼저 한 페이지에 보여줄 목록 숫자를 view로 지정 합니다
1페이지가 요청되었을 땐 1~10번 목록이 출력되야 하고 2페이지가 요청되었을 땐 11~20페이지가 출력되야 합니다
이것을 firstList ~ lastList만큼 출력하고 이동 할 페이지를 movePage라고 했을 때 firstList를 구하는 계산 공식은
(view * movePage) - view + 1 가 됩니다
movepage가 1일때
firstList => (10 * 1) - 10 + 1 = 1
lastList => movePage* view => 1 * 10 = 10
movepage가 2일때
firstList => (10 * 2) - 10 + 1 = 11
lastList=> movePage* view => 2 * 10 = 20
movepage가 3일때
firstList => (10 * 3) - 10 + 1 = 21
lastList => movePage* view => 3 * 10 = 30
기본생성자로는 1페이지의 목록 10개를 출력,
매개변수를 주었을땐 이동페이지의 목록 수를 조절하여 출력할 수 있게 옵션을 주었습니다
StoreService에 코드를 추가하고
List<Store> storeList(int category, int address, String sort, int page);
StoreServiceImp의 기존 코드를 수정/추가 합니다
@Override
public List<Store> storeList(int category, int address) {
return storeList(category, address, "주문접수 대기 중", 1);
}
@Override
public List<Store> storeList(int category, int address1, String sort, int page) {
Page p = new Page(page, 8);
Map<String, Object> map = new HashMap<>();
map.put("category", category);
map.put("address1", address1);
map.put("firstList", p.getFirstList());
map.put("lastList", p.getLastList());
map.put("sort", sort);
System.out.println("페이지 시작 = " + p.getFirstList() + " 페이지 끝 = " + p.getLastList());
return storeDAO.storeList(map);
}
기존의 첫번째 메서드는 두번째 메서드를 호출하게 변경하고
두번째 메서드는 생성자에 화면에 출력 할 view의 숫자를 조절 할 수 있게했습니다
StoreMapper의 storeList 페이지 설정부분을 수정합니다
WHERE RN BETWEEN #{firstList } AND ${lastList }
스크롤 시 페이지 추가는 간단하지만 페이지 이동버튼을 사용하려면 추가로 해야 할 작업이 있는데 다음장에서 구현해보겠습니다
'스프링부트' 카테고리의 다른 글
스프링부트+jsp로 배달사이트 만들기-21 인터셉터로 주소 불러오기 (0) | 2021.12.10 |
---|---|
스프링부트+jsp로 배달사이트 만들기-20 주문목록 수정/페이징 (0) | 2021.12.09 |
스프링부트+jsp로 배달사이트 만들기-17 xss 방어하기 (0) | 2021.12.09 |
스프링부트+jsp로 배달사이트 만들기-18 주문상세 페이지 (0) | 2021.12.09 |
스프링부트+jsp로 배달사이트 만들기-16 리뷰 사진 올리기 (0) | 2021.12.09 |