게으른 완벽주의자의 개발자 도전기
[shop]이미지와 함께 상품 등록하기 (enctype="multipart/form-data") 본문
1. html
<div class="col-5 ms-4">
<div class="row g-3">
<h4>상품등록</h4>
<form th:action="@{/admin/regItem}" method="post" enctype="multipart/form-data">
<div class="col-12 mb-3">
<div class="row g-3">
<div class="col mb-3">
상품 이름
<input type="text" class="form-control" placeholder="item_name" name="itemName">
</div>
</div>
<div class="row g-3">
<div class="col-6 mb-3">
상품 재고
<input type="number" class="form-control" placeholder="item_stock" min="1" name="itemStock">
</div>
<div class="col-6">
상품가격
<input type="text" class="form-control" placeholder="item_price" name="itemPrice">
</div>
</div>
<div class="row g-3">
<div class="col-12 mb-3">
카테코드
<select class="form-select" name="cateCode" id="cateCode">
<option selected>전체</option>
<th:block th:each="statusList : ${statusList}">
<option th:text ="${statusList.cateName}" th:value="${statusList.cateCode}"></option>
</th:block>
</select>
</div>
</div>
<div class="row g-3">
<div class="col-12 mb-3">
Main IMG <!-- 파일 여러개 선택 가능 multiple -->
<input type="file" class="form-control" name="mainImg">
</div>
</div>
<div class="row g-3">
<div class="col-12 mb-3">
Sub IMG
<input type="file" class="form-control" name="subImgs" multiple>
</div>
</div>
<div class="row g-3">
<div class="col-12">
상품 코맨트
<textarea class="form-control" rows="3" name="itemComment"></textarea>
</div>
</div>
<div class="row g-3" style="margin: 0 auto; text-align: center;">
<div class="col-12">
<button class="btn btn-outline-success" type="submit">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
fill="currentColor" class="bi bi-cart-plus"viewBox="0 0 16 16">
<path d="M9 5.5a.5.5 0 0 0-1 0V7H6.5a.5.5 0 0 0 0 1H8v1.5a.5.5 0 0 0 1 0V8h1.5a.5.5 0 0 0 0-1H9V5.5z" />
<path d="M.5 1a.5.5 0 0 0 0 1h1.11l.401 1.607 1.498 7.985A.5.5 0 0 0 4 12h1a2 2 0 1 0 0 4 2 2 0 0 0 0-4h7a2 2 0 1 0 0 4 2 2 0 0 0 0-4h1a.5.5 0 0 0 .491-.408l1.5-8A.5.5 0 0 0 14.5 3H2.89l-.405-1.621A.5.5 0 0 0 2 1H.5zm3.915 10L3.102 4h10.796l-1.313 7h-8.17zM6 14a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm7 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z" />
</svg> 등록 </button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
2. mapper
ITEM_CODE 가져오기
<select id="getItemCode" resultType="String">
SELECT 'ITEM_'||LPAD(NVL(MAX(TO_NUMBER(SUBSTR(ITEM_CODE, 6))),0)+1, 3, 0)
FROM SHOP_ITEM
</select>
상품등록
<insert id="regItem">
INSERT INTO SHOP_ITEM (
ITEM_CODE
, ITEM_NAME
, ITEM_STOCK
, ITEM_PRICE
, CATE_CODE
, ITEM_COMMENT
)VALUES(
#{itemCode} <!--select key 지웟으니 자료 넣어줘야 한다 -->
, #{itemName}
, #{itemStock}
, #{itemPrice}
, #{cateCode}
, #{itemComment}
)
</insert>
이미지 등록
<insert id="insertImgs">
INSERT INTO ITEM_IMG(
IMG_CODE
, ORIGIN_NAME
, ATTACHED_NAME
, IS_MAIN
, ITEM_CODE
)
<!-- itemVO에 list<ImgVO> imgList에 이미지 파일 데이터 다 넣었음
itemVO.getImgList(); getter가 호출된다. -->
<foreach collection="imgList" item="img" separator="UNION ALL" index="i">
SELECT
(SELECT 'IMG_'||LPAD(NVL(MAX(TO_NUMBER(SUBSTR(IMG_CODE, 5))) ,0) +1 + #{i}, 3, 0) FROM ITEM_IMG)
, #{img.originName}
, #{img.attachedName}
, #{img.isMain}
, #{img.itemCode}
FROM DUAL
</foreach>
</insert>
@Getter
@Setter
@ToString
public class ItemVO {
private String itemCode;
private String itemName;
private int itemPrice;
private String itemComment;
private String regDate;
private int itemStock;
private String cateCode;
private String itemStatus;
//association
private CateVO cateInfo;
private List<ImgVO> imgList;
}
아이템 코드조회
@Override
public String getItemCode() {
return sqlSession.selectOne("adminMapper.getItemCode");
}
상품등록(트렌젝션처리)
@Transactional(rollbackFor = Exception.class)
@Override
public void regItem(ItemVO itemVO) {
sqlSession.insert("adminMapper.regItem", itemVO);
sqlSession.insert("adminMapper.insertImgs", itemVO);
}
3. 사진 업로드 관련 메소드 만들기
public class UploadFileUtil {
//파일이 첨부될 경로 + "\\" 추가하기
private static final String UPLOAD_PATH = "D:\\자바관련자료\\dev\\workspaceSTS\\Shop\\src\\main\\resources\\static\\image\\";
//파일 첨부
public static ImgVO uploadFile(MultipartFile mainImg) {
//여기서 선언하여 return 시 사용가능하도록 만듦
String fileName = null; //첨부 파일명
String originFileName = null; //원본 파일명
//실제 첨부파일이 있을 때만 첨부파일 기능 실행. 첨부파일 없다면 빈문자로 들어옴
if(!mainImg.isEmpty()) {
//첨부파일 기능 (첨부하려는 원본 파일명)
originFileName = mainImg.getOriginalFilename();
//랜덤 문자 만들기(파일명 중복방지)
String uuid = UUID.randomUUID().toString();
//원본파일명에서 확장자(.jpg)만 가져오기
String extension = originFileName.substring(originFileName.lastIndexOf(".")); //"apple.jpg".substring(3) -> "le.jpg"
//indexOf("매개변수") 매개변수에 들어온 문자가 몇번째에 위치하는지 숫자로 알려줌
//lastIndexOf("매개변수") 중복된 문자 중 가장 마지막꺼 위치 알려줌
//첨부될 파일명 생성
fileName = uuid + extension;
try {
//파일 객체 생성 (파일경로 + 파일명)
File file = new File(UPLOAD_PATH + fileName);
//파일 업로드
mainImg.transferTo(file);
} catch (Exception e) {
e.printStackTrace();
}
}
//원본파일명 첨부파일명 둘다 가져가야 함 ImgVO
//리턴해야 하는 데이터 저장 위한 객체
ImgVO imgVO = new ImgVO();
imgVO.setAttachedName(fileName); //첨부파일명
imgVO.setOriginName(originFileName); //원본파일명
imgVO.setIsMain("Y");
return imgVO;
}
//다중 파일 첨부
public static List<ImgVO> multiUploadFile(List<MultipartFile> subImgs) {
List<ImgVO> list = new ArrayList<>();
//첨부된 파일의 개수만큼 첨부 할 것
for(MultipartFile subImg :subImgs) {
ImgVO vo = uploadFile(subImg); //uploadFile() 자체가 위에서 만든 메소드 불러온것
//메소드의 리턴값이 imgVO값으로 되기 때문에 list에 담는다.
vo.setIsMain("N");
list.add(vo);
}
return list;
}
}
4. controller
@PostMapping("/regItem")
public String regItem(ItemVO itemVO, MultipartFile mainImg
, List<MultipartFile> subImgs) {
//이미지 파일 첨부(메인이미지 첨부파일 하나)
//원본파일명, 첨부파일명, IS_MAIN
ImgVO uploadInfo = UploadFileUtil.uploadFile(mainImg);
//다중이미지파일 첨부 (서브이미지)
//원본파일명, 첨부파일명, IS_MAIN
List<ImgVO> uploadList = UploadFileUtil.multiUploadFile(subImgs);
//메인과 서브 이미지의 원본파일명, 첨부파일명, ismain 값 집어 넣음
uploadList.add(uploadInfo);
//item_code 상품과 이미지 둘다 아이템코드가 동일해야 한다.
//다음에 들어갈 item_code 조회하고(별도로 분리) 조회한 아이템코드로 insert 진행
String getItemCode = adminService.getItemCode();
itemVO.setItemCode(getItemCode);
//이미지 정보를 INSERT하기 위한 데이터를 가진 UPLOADLIST에
//조회한 ITEM_CODE값도 추가해 준다.
for(ImgVO vo :uploadList) {
vo.setItemCode(getItemCode);
}
//itemVO의 List<ImgVO> imgList에 전체 이미지 데이터 다 넣겠다
itemVO.setImgList(uploadList);
//상품 정보 insert + 이미지 정보 insert
itemVO.setItemStatus(ItemStatus.ON_SALE.toString());
adminService.regItem(itemVO);
return "redirect:/admin/main";
}
Enum을 활용하기 (ItemStatus)
우리는 ItemStatus의 default 값을 ON_SALE로 주기로 하였고, 필요에 따라 SOLD_OUT을 쓰고자 한다.
그래서 ItemStatus의 값을 세팅할 때 Enum에서 정의한 ON_SALE, SOLD_OUT 중에서
ON_SALE을 toString() 하고자 한다.
itemVO.setItemStatus(ItemStatus.ON_SALE.toString());
'Spring Boot' 카테고리의 다른 글
[shop] 사이드 메뉴판 active 추가하기 (th:classappend) (0) | 2022.10.09 |
---|---|
[shop]카테고리 등록 및 사용/미사용 변경 js(ajax) (0) | 2022.10.09 |
[shop] js활용하여 재고 변경 및 상품 상태 변경 (0) | 2022.10.09 |
[shop] 검색조건을 활용하여 아이템 검색하기 (0) | 2022.10.09 |
[shop] 날짜 (Calendar활용/localDate(참고) (0) | 2022.10.09 |