게으른 완벽주의자의 개발자 도전기
[shop]이미지를 추가하여 상품 등록하기(enctype="multipart/form-data") 본문
1. SHOP_ITEM 테이블
2. ITEM_IMAGE 테이블
상품등록 페이지에서 상품정보와 상품이미지를 등록하고자 한다.
1. jsp 화면
우리가 상품 이미지를 들고가기 위해서는 먼저 input 태그 type을 file로 지정해주어야 한다.
jsp form 태그에 enctype="multipart/form-data" 추가하여 작성한다.
또한, libs에 cos.jar 파일을 추가한다.
<form action="insertItem.ad" method="post" enctype="multipart/form-data">
<div class="regItem-container">
<div class="joinFormDiv">
<div>
<div>CATEGORY.</div>
<div>
<select name="cateCode">
<c:forEach var="category" items="${categoryList}">
<option value="${category.cateCode}">${category.cateName }</option>
</c:forEach>
</select>
</div>
</div>
<div>
<div>ITEM NAME.</div>
<div>
<input class="my-input" type="text" name="itemName" required>
</div>
</div>
<div>
<div>ITEM PRICE.</div>
<div>
<input class="my-input" type="text" name="itemPrice" required>
</div>
</div>
<div>
<div>ITEM COMMENT.</div>
<div>
<textarea rows="5" name="itemComment" ></textarea>
</div>
</div>
<div>
<div>MAIN FILE.</div>
<div>
<input type="file" name="mainImg">
</div>
</div>
<div>
<div>SUB FILE.</div>
<div>
<input type="file" name="subImg">
</div>
</div>
</div>
<div class="btnDiv">
<input class="btn" type="submit" value="등 록">
</div>
</div>
</form>
2. mapper에서 쿼리 작성
1) 상품등록 쿼리
<insert id="insertItem">
INSERT INTO SHOP_ITEM(
ITEM_NAME
, ITEM_PRICE
, ITEM_COMMENT
, CATE_CODE
, ITEM_CODE
) VALUES(
#{itemName} <- itemDTO.getItemName(); getter호출
, #{itemPrice}
, #{itemComment}
, #{cateCode}
, #{itemCode}
)
</insert>
2) 이미지 등록 쿼리
이미지는 하나가 아니라 여러개 들어갈 것이기 때문에 forEach문에서
List<ImgDTO> imgLIst 변수를 받는 Collection을 이용하여 데이터를 가져올 것이다.
ImgDTO에 list<ImgDTO> imgList를 추가하여 getter setter 만든다.
imgDTO.getImgList();로 데이터를 받기 위함.
우리가 taglib에서 사용하던 foreach와 비교하자면
<c: foreach items var> 가
<foreach collection item> 으로 사용됐다고 생각하면 된다.
<예제>
<foreach collection="empnoList" item="empno" open="(" close=")" separator="," index="i">
#{empno} + #{i}
</foreach>
collection의 리스트인 empnoList에서 item 하나를 꺼낼 때 난 그걸 empno라고 하겠다.
open : 반복 전 최초로 한 번 실행될 것 close: foreach 끝나고 실행될 것
separator 구분자. 반복 실행 시 마다 한 번씩 실행될 것
index : 01234 이런식 순번의 숫자를 의미
다중 INSERT 활용하여 작성
<insert id="insertImage">
INSERT INTO ITEM_IMAGE (
IMG_CODE
, ORIGIN_NAME
, ATTACHED_NAME
, IS_MAIN
, ITEM_CODE
)
<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_IMAGE)
, #{img.originName}
, #{img.attachedName}
, #{img.isMain}
, #{img.itemCode}
FROM DUAL
</foreach>
</insert>
★이미지 코드는 하나가 추가될 때 1씩 늘어나도록 할 것이다. 그래서 Index값을 이용해서
첫번째는 0 두번째는 1 세번째는 2가 플러스 되도록 쿼리문을 만들었다.
또한, select문이 foreach문으로 실행되기 때문에 union all 전 select 문의 imgCode 값이 0이라면, select문 이후로 union all이 시작되며 다시 select문이 실행된다.즉, 첫 select문이 커밋된 상태가 아니기 때문에 union all 이후 select문에서도imgCode도 여전히 0이 들어가 있다.
3) 상품과 아이템에 들어갈 #{itemCode}조회
<select id="selectNextItemCode" resultType="String">
SELECT 'ITEM_'||LPAD(NVL(MAX(TO_NUMBER(SUBSTR(ITEM_CODE, 6))),0) +1 , 3, 0)
FROM SHOP_ITEM
</select>
★상품테이블과, 이미지테이블이 있는데
상품테이블에 itemCode를 아래와 같이 설정했다.(기본키)
ITEM_CODE VARCHAR2(50) PRIMARY KEY
이미지 테이블에서 itemCode를 아래와 같이 설정했다.(외래키)
ITEM_CODE VARCHAR2(50) NOT NULL REFERENCES
SHOP_ITEM (ITEM_CODE) ON DELETE CASCADE
상품에 대한 사진이 두가지가 들어가더라도 itemCode는 동일하게 들어가야 한다.
4. 인터페이스 메소드
1)상품과 이미지 등록 메소드
void insertItem(ItemDTO item, ImgDTO img)
2) try catch문 활용
우리는 상품등록과 이미지등록 두가지가 모두 되어야 진정한 상품 등록으로 본다.
둘 중 하나라도 오류가 난 상태에서 등록이 실행되면 그건 의미 없는 데이터가 된다.
그래서 try catch문으로 우리가 원하는 트랜잭션이 완벽히 수행됐을 때 커밋이
될 수 있도록 만들어 준다.
@Override
public void insertItem(ItemDTO item, ImgDTO img) {
try {
상품 등록
sqlSession.insert("itemMapper.insertItem", item);
이미지 등록
sqlSession.insert("itemMapper.insertImage", img);
둘 다 실행됐을 때 커밋하겠다
sqlSession.commit();
} catch (Exception e) {
sqlSession.rollback();
e.printStackTrace();
}
}
5. CONTROLLER
else if(command.equals("/insertItem.ad")) {
input태그에서 전달받은 일반 데이터와 파일 데이터를 받기 위해서
multipartRequest 객체를 생성한다. (생성되자 마자 파일 첨부 실행됨)
1) String uploadPath ="C:\\Users\\user\\Desktop\\자바관련자료\\dev\\workspaceHtml\\Shop\\src\\main\\webapp\\images";
(★자신의 컴퓨터의 이미지파일 경로 복붙)
2) int uploadSize = 10*1024*1024; //10메가바이트(임의로 지정한 것 )
<객체 생성>
3)
MultipartRequest multi =
new MultipartRequest(request, uploadPath, uploadSize, "UTF-8", new DefaultFileRenamePolicy());
(★uploadPath 저장된 경로 uploadSize 파일저장용량 UTF-8 인코딩
new DefaultFileRenamePolicy() 파일 이름 중복 시 어떻게 처리하겠다)
4) <form태그 데이터 받아오기>
String itemName = multi.getParameter("itemName");
int itemPrice = Integer.parseInt(multi.getParameter("itemPrice"));
String itemComment = multi.getParameter("itemComment");
String cateCode = multi.getParameter("cateCode");
★String ItemCode = itemService.selectNextItemCode();
5) <ItemDTO 객체 생성>
ItemDTO item = new ItemDTO();
item.setCateCode(cateCode);
item.setItemComment(itemComment);
item.setItemName(itemName);
item.setItemPrice(itemPrice);
item.setItemCode(ltemCode);
6) 모든 이미지 정보를 저장하여 쿼리 실행 시 빈값을 채워 줄 객체
List<ImgDTO> imgList = new ArrayList<>();
<ITEM_IMAGE 테이블에 데이터 INSERT>
1) Enumeration<String> inputNames = multi.getFileNames();
(Enumeration<String> 자료형이 컬렉션일 때 사용
mapper에서 List<ImgDTO>imgList를 컬렉션으로 지정함)
(★multi.getFileNames(); 첨부파일이 있는 input태그의 name 속성의 값들 가져옴)
2) While문 사용
while(inputNames.hasMoreElements()) {
(★첨부파일이 있는 input태그의 name 속성 값 하나씩 출력
hasMoreElements() - 뒤에 남은 데이터가 있으면 True, 없으면 False를 반환한다.)
String inputName = inputNames.nextElement();
(nextElement() - 다음 데이터를 반환하겠다)
원본 파일명 가져오겠다. 파일 추가 안하면 null 들어감 -> 오류 원인
String originName = multi.getOriginalFileName(inputName);
3) 트랜잭션 활용( 상품정보와 이미지 함께 들어가야 의미 있으니까)
실제로 파일을 첨부했을 때만 전체 내용을 실행하겠다. (IF문 사용)
if(originName != null) {
(첨부된 파일명(originName), 실제 등록된 파일명(attachedName) )
(파일명 중복 시 임의로 변경되기 때문에 실 사용은 attachedName으로)
String attachedName = multi.getFilesystemName(inputName);
4) main 이미지 여부
String isMain = inputName.equals("mainImg") ? "Y" : "N";
(이미지 파일칸 name 속성으로 mainImg, subImg로 정했다)
(★다른 방법 main 이미지 여부
if(inputName.equals("mainImg")) {
isMain = "Y" ;
}
else {
isMain = "N";
} )
ImgDTO img = new ImgDTO();
img.setOriginName(originName);
img.setAttachedName(attachedName);
img.setIsMain(isMain);
img.setItemCode(ItemCode);
5) while문 밖에서 만든 List<ImgDTO> imgList에 img를 집어 넣기
imgList.add(img);
6) insert쿼리 반복
}
}
7) while문 안에 imgList.add(img);를 밑에 img에 넣어 주겠다
ImgDTO img = new ImgDTO();
img.setImgList(imgList);
8) shop_item 테이블에 데이터 insert (상품정보, 이미지)
itemService.insertItem(item, img);
page="regItemForm.ad";
isRedirect=true;
}
'servlet jsp' 카테고리의 다른 글
[shop]장바구니 원화표시 및 천단위 표시하기(#,##0, fmt 사용) (0) | 2022.08.22 |
---|---|
[shop]상품 상세페이지(이미지 두장 넣기, 총 가격 변경(script 이벤트 사용)) (0) | 2022.08.21 |
이클립스 파일 임포트 import, 엑스포트 export 하는 방법 (0) | 2022.08.13 |
Session Cookie (0) | 2022.08.06 |
톰캣 오류 Tomcat v8.5 server at localhost has encountered a problem 2가지 방법 (0) | 2022.08.06 |