상품수정
상품수정화면
➡️ 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>
➡️ 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>
➡️ 1) 리턴이 Goods 타입인 메소드를 선언한다.
2) Mapper에서 선언한 메소드를 호출한다.
[코드]GoodsService.java
/** * 상품코드별 상품조회 * @param goodsCode * @return */ public Goods getGoodsByCode(String goodsCode) { Goods goodsInfo = goodsMapper.getGoodsByCode(goodsCode); return goodsInfo; }
➡️ 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"; }
➡️ 모델을 통해 전달받은 데이터를 타임리프 문법을 사용해서 화면에 출력한다.
[코드]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>
![](https://blog.kakaocdn.net/dn/cGQlZK/btsp1gkH7Cm/St7IpyCXKs5yl2kCcamwn0/img.png)
상품수정처리
➡️ 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"; }
➡️ 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>
➡️ mapper 에 선언된 메서드를 호출한다. (반환값은 따로 사용하지 않기 때문에 없어도 된다.)
[코드] GoodsService.java
/** * 상품 수정 * @param goods */ public void modifyGoods(Goods goods) { goodsMapper.modifyGoods(goods); }
➡️ 서비스단에서 선언한 메서드를 호출한다.
[코드] GoodsController.java
/** * 상품수정처리 * @param goods * @return */ @PostMapping("/modifyGoods") public String modifyGoods(Goods goods) { log.info("goods : {}", goods); goodsService.modifyGoods(goods); return "redirect:/goods/goodsList"; }
상품삭제
상품삭제화면
➡️ 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"; }
삭제 화면에 상품정보(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"; }
➡️ 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) 상품삭제 화면에서 삭제버튼 클릭 시 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"; }
➡️ 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"; }
➡️ 1) ERD를 확인하여 연결된 테이블을 확인한다.
2) 주문 테이블의 상품주문이력 삭제 → 상품 삭제
➡️ 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>
➡️ mapper에서 선언한 메소드를 호출한다. 결과값은 사용하지 않는다.
[코드] GoodsService.java
/** * 특정상품삭제 * @param goodsCode */ public void removeGoods(String goodsCode) { goodsMapper.removeOrderByGoodsCode(goodsCode); goodsMapper.removeGoodsByGoodsCode(goodsCode); }
➡️ 검증이 성공 했을 때 삭제 처리 하는 서비스를 호출한다.
[코드] 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