멋쟁이v의 개발일지

[Spring] Mybatis 상품관리(2) - 상품수정, 삭제 본문

0년차/Spring

[Spring] Mybatis 상품관리(2) - 상품수정, 삭제

멋쟁이v 2023. 8. 5. 17:57
728x90
320x100


상품수정

상품수정화면
1️⃣
Controller, html

➡️ 1) 상품목록에서 수정버튼을 클릭했을 때 주소요청을 하는데, 쿼리파라미터에 goodsCode=’값’ 을 넘겨준다. (/goods/modifyGoods(goodsCode=${값}))

2) Controller에서 메소드를 만든다. (주소맵핑)

3) 쿼리파라미터를 @RequestParam으로 값을 매개변수에 받아온다.

4) 리턴으로는 수정화면을 반환한다. (html)

  • [코드]GoodsController.java
    /**
     * 상품수정화면
     * @param model
     * @return
     */
    @GetMapping("/modifyGoods")
    public String modifyGoods(Model model,
                              @RequestParam(value = "goodsCode") String goodsCode) {
    
        model.addAttribute("title", "상품수정화면");
    
        return "goods/modifyGoods";
    }
  • [코드]modifyGoods.html
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org"
          xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
          layout:decorate="~{layout/default}">
    
    <head>
        <link rel="stylesheet" type="text/css" th:href="@{/css/table.css}">
        <style>
            input {
                width: 98%;
                height: 23px;
            }
    
            select {
                width: 98%;
                text-align: center;
                height: 23px;
            }
    
            #modifyGoodsBtn, #resetBtn {
                width: 49%;
                height: 25px;
            }
        </style>
    </head>
    
    <th:block layout:fragment="customContents">
        <form id="modifyGoodsForm" th:action="@{/goods/modifyGoods}" method="post">
            <table>
                <tbody>
                <tr>
                    <td>
                        <label for="goodsCode">상품코드</label>
                    </td>
                    <td>
                        <input type="text" id="goodsCode" name="goodsCode"
                               readonly="readonly"/>
                    </td>
                </tr>
                <tr>
                    <td>
                        <label for="goodsName">상품명</label>
                    </td>
                    <td>
                        <input type="text" id="goodsName" name="goodsName"
                               placeholder="상품명을 입력해주세요."/>
                    </td>
                </tr>
                <tr>
                    <td>
                        <label for="goodsPrice">상품가격</label>
                    </td>
                    <td>
                        <input type="text" id="goodsPrice" name="goodsPrice"
                               placeholder="상품가격을 입력해주세요."/>
                    </td>
                </tr>
                <tr>
                    <td>
                        <label for="goodsSellerId">판매자</label>
                    </td>
                    <td>
                        <select name="goodsSellerId" id="goodsSellerId">
                            <option value="">===판매자를 선택해주세요.===</option>
                            <th:block>
                                <option>
                                    ID :::: 이름
                                </option>
                            </th:block>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <button type="submit" id="modifyGoodsBtn">수정완료</button>
                        <button type="reset" id="resetBtn">입력취소</button>
                    </td>
                </tr>
                </tbody>
            </table>
        </form>
    </th:block>
    </html>

2️⃣
Mapper

➡️ 1) 상품코드별 상품을 조회하는 쿼리를 작성한다.

2) 인터페이스와 xml을 연결시켜준다.

  • [코드]GoodsMapper.java
    // 상품코드별 상품조회
    public Goods getGoodsByCode(String goodsCode);
  • [코드]GoodsMapper.xml
    <select id="getGoodsByCode" parameterType="String" resultMap="goodsResultMap">
        /* 상품코드별 상품조회 */
        SELECT
            g.g_code,
            g.g_name,
            g.g_price,
            g.g_seller_id,
            g.g_reg_date
        FROM
            tb_goods AS g
        WHERE
            g.g_code = #{goodsCode};
    </select>

3️⃣
Service

➡️ 1) 리턴이 Goods 타입인 메소드를 선언한다.

2) Mapper에서 선언한 메소드를 호출한다.

  • [코드]GoodsService.java
    /**
     * 상품코드별 상품조회
     * @param goodsCode
     * @return
     */
    public Goods getGoodsByCode(String goodsCode) {
    
        Goods goodsInfo = goodsMapper.getGoodsByCode(goodsCode);
    
        return goodsInfo;
    }

4️⃣
Controller

➡️ 1) Service에서 선언한 상품코드별 상품조회와 판매자의 정보를 조회한 메소드를 호출한다.

2) 두 객체를 model을 통해서 화면에 전달한다.

  • [코드]Controller.java
    /**
     * 상품수정화면
     * @param model
     * @return
     */
    @GetMapping("/modifyGoods")
    public String modifyGoods(Model model,
                              @RequestParam(value = "goodsCode") String goodsCode) {
    
        Goods goodsInfo = goodsService.getGoodsByCode(goodsCode);
        List<Member> sellerInfoList = goodsService.getSellerInfoList();
    
        model.addAttribute("title", "상품수정화면");
        model.addAttribute("goodsInfo", goodsInfo);
        model.addAttribute("sellerInfoList", sellerInfoList);
    
        return "goods/modifyGoods";
    }

5️⃣
html

➡️ 모델을 통해 전달받은 데이터를 타임리프 문법을 사용해서 화면에 출력한다.

  • [코드]modifyGoods.html
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org"
          xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
          layout:decorate="~{layout/default}">
    
    <head>
        <link rel="stylesheet" type="text/css" th:href="@{/css/table.css}">
        <style>
            input {
                width: 98%;
                height: 23px;
            }
    
            select {
                width: 98%;
                text-align: center;
                height: 23px;
            }
    
            #modifyGoodsBtn, #resetBtn {
                width: 49%;
                height: 25px;
            }
        </style>
    </head>
    
    <th:block layout:fragment="customContents">
        <form id="modifyGoodsForm" th:action="@{/goods/modifyGoods}" method="post">
            <table th:object="${goodsInfo}">
                <tbody>
                <tr>
                    <td>
                        <label for="goodsCode">상품코드</label>
                    </td>
                    <td>
                        <input type="text" id="goodsCode" name="goodsCode"
                               th:value="*{goodsCode}" readonly="readonly"/>
                    </td>
                </tr>
                <tr>
                    <td>
                        <label for="goodsName">상품명</label>
                    </td>
                    <td>
                        <input type="text" id="goodsName" name="goodsName"
                               th:value="*{goodsName}" placeholder="상품명을 입력해주세요."/>
                    </td>
                </tr>
                <tr>
                    <td>
                        <label for="goodsPrice">상품가격</label>
                    </td>
                    <td>
                        <input type="text" id="goodsPrice" name="goodsPrice"
                               th:value="*{goodsPrice}" placeholder="상품가격을 입력해주세요."/>
                    </td>
                </tr>
                <tr>
                    <td>
                        <label for="goodsSellerId">판매자</label>
                    </td>
                    <td>
                        <select name="goodsSellerId" id="goodsSellerId">
                            <option value="">===판매자를 선택해주세요.===</option>
                            <th:block th:unless="${#lists.isEmpty(sellerInfoList)}"
                                      th:each="l : ${sellerInfoList}">
                                <option th:value="${l.memberId}"
                                        th:selected="${l.memberId} == *{goodsSellerId}"
                                        th:text="|${l.memberId} :::: ${l.memberName}|">
                                </option>
                            </th:block>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <button type="submit" id="modifyGoodsBtn">수정완료</button>
                        <button type="reset" id="resetBtn">입력취소</button>
                    </td>
                </tr>
                </tbody>
            </table>
        </form>
    </th:block>
    </html>

상품수정처리
1️⃣
Controller

➡️ 1) 수정화면에서 수정완료 버튼을 눌렀을 때 form 안에 있는 데이터들을 post 방식으로 전달한다.

2) controller 에서 Post 로 주소요청 하는 메소드를 만들어 준다.

3) 커맨드 객체를 활용해서 dto에 set 되어있는 데이터들을 매개변수로 가져온다.

4) 리턴은 상품 리스트 화면으로 리다이렉트 해준다.

  • [코드] GoodsController.java
    /**
     * 상품수정처리
     * @param goods
     * @return
     */
    @PostMapping("/modifyGoods")
    public String modifyGoods(Goods goods) {
    
        log.info("goods : {}", goods); // 커맨드 객체를 지원
    		// form에 있던 데이터들이 객체에 담긴다.
    
        return "redirect:/goods/goodsList";
    }

2️⃣
Mapper

➡️ 1) 업데이트 쿼리문 작성

2) 동적 쿼리를 사용해서 값이 있을 때와 없을 때 동적으로 변할 수 있도록 해준다. (수정하고 싶은 항목이 한가지만 있을 수도 있기 때문에)

3) 쿼리문이 실행되면 반환값은 숫자다. (select 제외)

  • [코드] GoodsMapper.java
    // 상품수정
    public int modifyGoods(Goods goods);
  • [코드] GoodsMapper.xml
    <update id="modifyGoods" parameterType="Goods">
        UPDATE tb_goods
        <set>
            <if test="goodsName != null and goodsName != ''">
                g_name = #{goodsName},
            </if>
            <if test="goodsPrice != null and goodsPrice != ''">
                g_price = #{goodsPrice},
            </if>
            <if test="goodsSellerId != null and goodsSellerId != ''">
                g_seller_id = #{goodsSellerId},
            </if>
        </set>
        WHERE
            g_code = #{goodsCode};
    </update>

3️⃣
Service

➡️ mapper 에 선언된 메서드를 호출한다. (반환값은 따로 사용하지 않기 때문에 없어도 된다.)

  • [코드] GoodsService.java
    /**
     * 상품 수정
     * @param goods
     */
    public void modifyGoods(Goods goods) {
        goodsMapper.modifyGoods(goods);
    }

4️⃣
Controller

➡️ 서비스단에서 선언한 메서드를 호출한다.

  • [코드] GoodsController.java
    /**
     * 상품수정처리
     * @param goods
     * @return
     */
    @PostMapping("/modifyGoods")
    public String modifyGoods(Goods goods) {
    
        log.info("goods : {}", goods);
    
        goodsService.modifyGoods(goods);
    
        return "redirect:/goods/goodsList";
    }


상품삭제

상품삭제화면
1️⃣
Controller

➡️ 1) 상품목록에서 삭제버튼을 클릭했을 때 주소요청 시 쿼리파라미터로 goodsCode를 넘겨준다. (/goods/removeGoods(goodsCode=${값}))

2) Controller에서 메소드를 만든다. (주소맵핑)

3) 쿼리파라미터를 @RequestParam으로 값을 받아서 매개변수에 담아준다.

4) 리턴으로는 삭제화면을 반환한다. (html)

  • [코드] GoodsController.java
    /**
     * 상품삭제화면
     * @param goodsCode
     * @param model
     * @return
     */
    @GetMapping("/removeGoods")
    public String removeGoods(@RequestParam(value = "goodsCode") String goodsCode,
                              Model model) {
    
        model.addAttribute("title", "상품삭제");
    
        return "goods/removeGoods";
    }

2️⃣
삭제화면

삭제 화면에 상품정보(goodsCode, goodsName)와 판매자 비밀번호를 적는 화면으로 구성한다.

➡️ 1) 기존에 만들어 놓은 상품코드를 통해 상품정보를 가져오는 service 단을 호출해서 정보를 가져온다.

2) 가져온 정보들을 model을 통해 전달한다.

  • [코드] GoodsController.java
    /**
     * 상품삭제화면
     * @param goodsCode
     * @param model
     * @return
     */
    @GetMapping("/removeGoods")
    public String removeGoods(@RequestParam(value = "goodsCode") String goodsCode,
                              Model model,
                              @RequestParam(value = "msg", required = false) String msg) {
    
        Goods goodsInfo = goodsService.getGoodsByCode(goodsCode);
        String goodsName = goodsInfo.getGoodsName();
        String goodsSellerId = goodsInfo.getGoodsSellerId();
    
        model.addAttribute("title", "상품삭제");
        model.addAttribute("goodsCode", goodsCode);
        model.addAttribute("goodsName", goodsName);
        model.addAttribute("goodsSellerId", goodsSellerId);
        if(msg != null) model.addAttribute("msg", msg);
    
        return "goods/removeGoods";
    }

3️⃣
html

➡️ model을 통해 전달받은 데이터를 화면에 출력하고, 활용한다.

  • [코드] removeGoods.html
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org"
          xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
          layout:decorate="~{layout/default}">
    
    <head>
        <link rel="stylesheet" type="text/css" th:href="@{/css/table.css}">
        <style>
            input {
                width: 98%;
                height: 23px;
            }
    
            select {
                width: 98%;
                text-align: center;
                height: 23px;
            }
    
            #removeGoodsBtn, #resetBtn {
                width: 49%;
                height: 25px;
            }
        </style>
    </head>
    
    <th:block layout:fragment="customJs">
        <script th:src="@{/js/jquery-3.7.0.js}"></script>
        <script type="text/javascript" th:inline="javascript">
            // 자바스크립트 작성 공간
        </script>
    </th:block>
    
    <th:block layout:fragment="customContents">
        <form id="removeGoodsForm" th:action="@{/goods/removeGoods}" method="post">
            <table>
                <tbody>
                <tr>
                    <td>
                        <label>상품정보</label>
                    </td>
                    <td>
                        <label th:text="|상품코드:${goodsCode}, 상품명:${goodsName}|"></label>
                    </td>
                </tr>
                <tr>
                    <td>
                        <label for="goodsSellerPw">판매자비밀번호</label>
                    </td>
                    <td>
                        <input type="hidden" name="goodsSellerId" th:value="${goodsSellerId}"/>
                        <input type="text" id="goodsSellerPw" name="goodsSellerPw"
                               placeholder="판매자의 비밀번호를 입력해주세요."/>
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <button type="submit" id="removeGoodsBtn">삭제완료</button>
                        <button type="reset" id="resetBtn">입력취소</button>
                    </td>
                </tr>
                </tbody>
            </table>
        </form>
    </th:block>
    </html>

상품삭제리
1️⃣
Controller, html

➡️ 1) 상품삭제 화면에서 삭제버튼 클릭 시 form안에 정보들이 post 방식으로 전송된다. (화면에 불필요한 내용은 input 박스의 hidden 으로 감춘다. → 상품코드, 상품이름, 판매자 아이디의 값)

2) 제이쿼리를 사용해서 태그를 생성하는 방법 사용

3) controller 에서 post로 주소요청 하는 메소드를 생성한다.

4) 상품코드와 판매자 비밀번호를 매개변수로 받는다.

👉🏻 th:inline : 자바스크립트에서 타임리프 구문을 사용하기 위해 제공하는 기능.

  • [코드] removeGoods.html
    <th:block layout:fragment="customJs">
        <script th:src="@{/js/jquery-3.7.0.js}"></script>
        <script type="text/javascript" th:inline="javascript">
    				/* 자바스크립트 작성 공간 */
            let msg = '[[${msg}]]';
            if(msg != 'null') alert(msg);
    
            $('#removeGoodsBtn').click(function (e) {
              e.preventDefault();
              let goodsCode = [[${goodsCode}]];
              let goodsName = [[${goodsName}]];
              let goodsSellerId = [[${goodsSellerId}]];
              const $goodsCode = $('<input />',{'type':'hidden', 'name':'goodsCode', 'value':goodsCode});
              const $goodsName = $('<input />',{'type':'hidden', 'name':'goodsName', 'value':goodsName});
              const $goodsSellerId = $('<input />',{'type':'hidden', 'name':'goodsSellerId', 'value':goodsSellerId});
              $('#removeGoodsForm').append($goodsCode);
              $('#removeGoodsForm').append($goodsName);
              $('#removeGoodsForm').append($goodsSellerId);
    
    					// 생성한 input 데이터와 함께 form을 전송한다.
              $('#removeGoodsForm').submit();
            });
        </script>
    </th:block>
  • [코드] GoodsController.java
    @PostMapping("/removeGoods")
    public String removeGoods(@RequestParam(value = "goodsCode") String goodsCode,
                              @RequestParam(value = "goodsSellerPw") String goodsSellerPw) {
    
        return "redirect:/goods/goodsList";
    }

2️⃣
Controller

➡️ 1) 삭제 화면에서 비밀번호를 입력했을 때 회원 여부 검증을 진행한다.

2) 상품코드로 상품 정보들을 불러와서 판매자 아이디를 가져온다.

3) 판매자 아이디를 기존 서비스단에 생성한 메서드(회원 검증 로직)을 통해 검증한다.

4) 검증이 완료 되면 삭제처리 후 상품 리스트로 리다이렉트 하고, 실패하면 다시 삭제화면으로 리다이렉트 해준다.

4) RedirectAttributes를 통해서 다시 삭제화면으로 리다이렉트 될 때 상품코드를 넘겨줘야 하고, 추가로 메세지도 넘겨준다.

👉🏻 RedirectAttributes : 리다이렉트 시 model 처럼 데이터를 전달해 줄 수 있는 기능을 제공한다.

  • [코드] GoodsController.java
    /**
     * 상품 삭제 처리
     * @return
     */
    @PostMapping("/removeGoods")
    public String removeGoods(@RequestParam(value = "goodsCode") String goodsCode,
                              @RequestParam(value = "goodsSellerPw") String goodsSellerPw,
                              RedirectAttributes reAttr) {
    
        Goods goodsInfo = goodsService.getGoodsByCode(goodsCode);
        String goodsSellerId = goodsInfo.getGoodsSellerId();
    
        // 회원 여부 검증
        Map<String, Object> isValidMap = memberService.isValidMember(goodsSellerId, goodsSellerPw);
        boolean isValid = (boolean) isValidMap.get("isValid");
    
        // 회원 비밀번호 일치시 회원삭제
        if(isValid) {
    			
    				// 삭제 처리
    
            return "redirect:/goods/goodsList";
        }
    
        reAttr.addAttribute("goodsCode", goodsCode);
        reAttr.addAttribute("msg", "회원의 정보가 일치하지 않습니다.");
    
        return "redirect:/goods/removeGoods";
    }

3️⃣
상품 삭제 처리

➡️ 1) ERD를 확인하여 연결된 테이블을 확인한다.

2) 주문 테이블의 상품주문이력 삭제 → 상품 삭제

4️⃣
Mapper

➡️ 1) 상품코드별 주문 이력 삭제

2) 상품코드별 상품 삭제

  • [코드] GoodsMapper.java
    // 상품코드별 주문이력삭제
    public int removeOrderByGoodsCode(String goodsCode);
    
    // 상품코드별 상품삭제
    public int removeGoodsByGoodsCode(String goodsCode);
  • [코드] GoodsMapper.xml
    <delete id="removeOrderByGoodsCode" parameterType="String">
        /* 상품코드별 주문이력삭제 */
        DELETE
            o
        FROM
            tb_goods AS g
            INNER JOIN
            tb_order AS o
            ON
            g.g_code = o.o_g_code
        WHERE
            g.g_code = #{goodsCode};
    </delete>
    
    <delete id="removeGoodsByGoodsCode" parameterType="String">
        /* 상품코드별 상품삭제 */
        DELETE
        FROM
            tb_goods
        WHERE
            g_code = #{goodsCode};
    </delete>

5️⃣
Service

➡️ mapper에서 선언한 메소드를 호출한다. 결과값은 사용하지 않는다.

  • [코드] GoodsService.java
    /**
     * 특정상품삭제
     * @param goodsCode
     */
    public void removeGoods(String goodsCode) {
    
        goodsMapper.removeOrderByGoodsCode(goodsCode);
        goodsMapper.removeGoodsByGoodsCode(goodsCode);
    
    }

6️⃣
Controller

➡️ 검증이 성공 했을 때 삭제 처리 하는 서비스를 호출한다.

  • [코드] GoodsController.java
    /**
     * 상품 삭제 처리
     * @return
     */
    @PostMapping("/removeGoods")
    public String removeGoods(@RequestParam(value = "goodsCode") String goodsCode,
                              @RequestParam(value = "goodsSellerPw") String goodsSellerPw,
                              RedirectAttributes reAttr) {
    
        Goods goodsInfo = goodsService.getGoodsByCode(goodsCode);
        String goodsSellerId = goodsInfo.getGoodsSellerId();
    
        // 회원 여부 검증
        Map<String, Object> isValidMap = memberService.isValidMember(goodsSellerId, goodsSellerPw);
        boolean isValid = (boolean) isValidMap.get("isValid");
    
        // 회원 비밀번호 일치시 회원삭제
        if(isValid) {
    			
    				// 삭제 처리
    				goodsService.removeGoods(goodsCode);
    
            return "redirect:/goods/goodsList";
        }
    
        reAttr.addAttribute("goodsCode", goodsCode);
        reAttr.addAttribute("msg", "회원의 정보가 일치하지 않습니다.");
    
        return "redirect:/goods/removeGoods";
    }


tag : #spring #mybatis #커맨드객체 #dto #동적쿼리 #update #set #th:inline #RedirectAttributes #delete


Uploaded by N2T

728x90
320x100
Comments