국비/Project-2 쇼핑몰

2023.05.24 83일차 Team Project

춘핑이 2023. 5. 24. 16:32

83일차

필수 페이징 검색
추가할것
빈칸이면 submit버튼 비활성화
공개 비공개 기능?
재고별로 보기

오늘할일
페이지네이션
검색하기

1.페이지네이션

1.1 컨트롤러

page값을 받아온다.

// 상품 목록 페이지
@GetMapping("list")
public String list(Model model,
        @RequestParam(value = "page", defaultValue = "1") Integer page,
    // List<ProductView> productList = productService.getViewList();
    Map<String, Object> result = productService.getViewList(page, type, search, stockQuantity);
    model.addAllAttributes(result);
    return "admin/product/list";
}

1.2 서비스

페이징에 필요한 정보
pageSize = 몇개씩 게시물을 보여줄지 10개씩
startIndex = 쿼리에서 시작하는 index 0 10 20 이런식으로 변화한다.
count = 마지막페이지를 알기 위해서 글의 총 개수 필요하다.
lastPage = 마지막페이지 (글총개수 -1) / 보여줄 글개수 + 1
leftPageNumber = 페이지네이션 왼쪽번호
110일때 1 1120일때 11 20에서30일때 21이런식으로 변화한다.
(page - 1) / pageSize * pageSize + 1;
(현재 페이지에서 -1 /보여줄개수) * 10 + 1해주면된다.
rightPageNumber = 페이지 네이션 오른쪽 번호 왼쪽번호 + 9
110쪽씩 보여줄 것이기때문에
prevPageNumber = 이전페이지 번호 -10으로가면된다.
nextPageNumber = 다음페이지 번호 +10으로 가면된다.
이전 다음은 정하는 사람 마음인데 나의 경우는 아예 다음페이지 1
10 11~20이런식으로 변화하게 만들었다.

// 상품목록
@Override
public Map<String, Object> getViewList(Integer page, String type, String search, Integer stockQuantity) {
    // 0~10 10~20 20~30
    Integer pageSize = 10; // 10 20 30 인데 mariadb 10씩
    Integer startIndex = (page - 1) * pageSize; // 0 10 20

    // 페이지 네이션에 필요한 정보
    // 전체 레코드 수
    Integer count = productMapper.countAll(t);

    // 마지막 페이지 번호
    // 총 글개수 -1 / pageSize + 1
    Integer lastPage = (count - 1) / pageSize + 1;

    // 페이지네이션 왼쪽번호 1 11 21 31
    Integer leftPageNumber = (page - 1) / pageSize * pageSize + 1;
    leftPageNumber = Math.max(leftPageNumber, 1);

    // 페이지네이션 오른쪽 번호
    Integer rightPageNumber = leftPageNumber + 9;
    rightPageNumber = Math.min(rightPageNumber, lastPage);

    // 현재 페이지
    Integer currentPageNumber = page;

    // 이전페이지
    Integer prevPageNumber = leftPageNumber - 10;

    // 다음 페이지
    Integer nextPageNumber = leftPageNumber + 10;

    Map<String, Object> pageInfo = new HashMap<>();
    pageInfo.put("lastPageNumber", lastPage);
    pageInfo.put("leftPageNumber", leftPageNumber);
    pageInfo.put("rightPageNumber", rightPageNumber);
    pageInfo.put("currentPageNumber", currentPageNumber);
    pageInfo.put("prevPageNumber", prevPageNumber);
    pageInfo.put("nextPageNumber", nextPageNumber);

    List<ProductView> productList = productMapper.selectAllPaging(page, startIndex, pageSize, type, search, stockQuantity);
    return Map.of("pageInfo", pageInfo, "productList", productList);
}

1.3 매퍼

<select id="selectAllPaging" resultMap="productViewMap">
    SELECT * FROM productview
    ORDER BY product_id DESC
    LIMIT #{startIndex}, #{pageSize}
</select>

2. 검색기능

url에 파라미터 유지하기, 검색시 남아잇게하기 등등이 필요하다.

2.1 컨트롤러

type과 search를 파라미터로 받는다.

// 상품 목록 페이지
@GetMapping("list")
public String list(Model model,
        @RequestParam(value = "page", defaultValue = "1") Integer page,
        @RequestParam(value = "type", required = false) String type,
        @RequestParam(value = "search", defaultValue = "") String search,
    // List<ProductView> productList = productService.getViewList();
    Map<String, Object> result = productService.getViewList(page, type, search, stockQuantity);
    model.addAllAttributes(result);
    return "admin/product/list";
}

2.2 서비스

매퍼에서목록을 불러올때 type과 search파라미터를 전달한다.

Integer count = productMapper.countAll(type, search);
List<ProductView> productList = productMapper.selectAllPaging(page, startIndex, pageSize, type, search);

2.3 매퍼

다이나믹 sql을 통해서 조건에따라 WHERE문이 추가되게 한다.
all일때는 모든 조건문이 들어가도록 작성해주었다.
where태그로 감싸면 조건에 따라 앞의 OR이나 AND가 알아서 없어지거나 붙는다.

<!-- 글 개수 -->
<select id="countAll" resultType="Integer">
    <bind name="pattern" value="'%' + search + '%'" />
    SELECT count(product_id) FROM
    <if test="stockQuantity != null and stockQuantity != ''">
        (SELECT * FROM productview WHERE stock_quantity &lt;=
        #{stockQuantity}) f
    </if>
    <if test="stockQuantity == null or stockQuantity == ''">
        productview
    </if>
    <where>
        <if test="type eq 'all' or type eq 'productName'">
            product_name LIKE #{pattern}
        </if>
        <if test="type eq 'all' or type eq 'countryOfOrigin'">
            OR country_of_origin LIKE #{pattern}
        </if>
        <if test="type eq 'all' or type eq 'categoryName'">
            OR category_name LIKE #{pattern}
        </if>
    </where>
</select>

<!-- 페이징과 검색이 적용된 상품 목록 -->
<select id="selectAllPaging" resultMap="productViewMap">
    <bind name="pattern" value="'%' + search + '%'" />
    SELECT * FROM productview

    <where>
        <if test="type eq 'all' or type eq 'productName'">
            product_name LIKE #{pattern}
        </if>
        <if test="type eq 'all' or type eq 'countryOfOrigin'">
            OR country_of_origin LIKE #{pattern}
        </if>
        <if test="type eq 'all' or type eq 'categoryName'">
            OR category_name LIKE #{pattern}
        </if>
        <if test="stockQuantity != null and stockQuantity != ''">
            AND stock_quantity &lt; #{stockQuantity}
        </if>
    </where>

    ORDER BY product_id DESC
    LIMIT #{startIndex}, #{pageSize}
</select>

3. 100개이하 보기

stockQuantity이라는 파라미터를 따로만들어서 있으면 조건문에 들어가게 만들었다.

4. 공개비공개기능

<update id="changeProductPub" parameterType="java.util.Map">
    UPDATE productview
    SET pub =
    CASE
    WHEN product_id IN
    <foreach collection="openIds" item="oid" open="(" close=")"
        separator=",">
        #{oid}
    </foreach>
    THEN 1
    ELSE 0
    END
    WHERE product_id IN
    <foreach collection="idsArr" item="ids" open="(" close=")"
        separator=",">
        #{ids}
    </foreach>

2023.05.31

공개 비공개 기능에 대한 쿼리문을 짯다.
체크박스이름을 openIds로 짓고 체크된것은 openIds배열에 담고 모든 체크박스를 idsArr에 담았다.
case when 구문을 활용해서 모든 id배열에서 체크된것은 1로 아닌것들은 0으로 만드는 쿼리가 작성이 되었다.
그런데 이부분에서 form요청을 해서 리다이렉트를 하게 되니 체크처리 확인이 어려운 문제가 발생했다.
이를 해결하기 위해 ajax로 요청을 변경할 예정이다.