스프링부트+jsp로 배달사이트 만들기-19 매장목록 수정/페이징

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 }

 

 

view를 8로 설정했을 때

스크롤 시 페이지 추가는 간단하지만 페이지 이동버튼을 사용하려면 추가로 해야 할 작업이 있는데 다음장에서 구현해보겠습니다