간펴니
간편 자바프로그래밍
간펴니
전체 방문자
오늘
어제
  • 전체보기 (185)
    • 알고리즘 (2)
    • JAVA (69)
      • 이펙티브 자바 (47)
      • JAVA 병렬프로그래밍 (5)
      • 자바 (17)
    • SPRING (60)
      • Spring (12)
      • IceWater Community (37)
      • Homme Shop (10)
      • 토비의 스프링 (1)
    • SPRING BOOT (4)
      • WhiteRecord (7)
    • 오류 (9)
    • DB (10)
      • ORACLE (5)
      • MYSQL (1)
      • MYBATIS (4)
      • JPA (0)
      • 대용량 데이터 베이스 (0)
      • SQL (0)
    • FRONT (8)
      • JSP (2)
      • JavaScript (2)
      • Jquery (3)
      • Thymeleaf (1)
    • AWS (6)
    • JNI (10)
    • 회고 (0)
    • MQ (0)
    • Radis (0)
    • Git (0)
    • Docker (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • 블로그 컨셉 변경

인기 글

태그

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
간펴니

간편 자바프로그래밍

[스프링]쇼핑몰 - 상품 등록
SPRING/Homme Shop

[스프링]쇼핑몰 - 상품 등록

2021. 12. 7. 20:25
728x90

이번 프로젝트는 남성의류 쇼핑몰이다. 스프링과 오라클 , jsp를 사용해 구현했다.

 

저번 프로젝트에서 구현했던 회원이나 게시판등의 기능들도 구현했지만 

 

쇼핑몰 기능 부분만 작성해보려고 한다.

 

 


 

 

 

 

 

먼저 로직의 설명이다.

 

기본정보에서 상품페이지에 표시 될 정보들을 입력한다 ( 카테고리 , 제목 , 내용 등...)

 

입력한 정보가 상품내용페이지에서 표시된다.

 

 


 

기본정보를 입력 후 , 옵션설정에서 옵션추가를 눌러서 원하는 만큼의 옵션과 수량을 입력 할 수 있다.

 

상품자체의 수량이 아닌, 상품의 옵션 ( 95, red / 100,blue ) 등 같은 제품이라도 옵션에 따라 수량이 다를 수 있기 때문

 

에, 쇼핑몰 재고관리의 편의성을 높이기 위해 이런 방식으로 구현했다.

 


다음은 이미지 설정이다.

 

메인이미지와 서브이미지를 올릴 수 있다.

 

 

로직순서는

 

상품테이블에 insert -

옵션테이블에 옵션의 개수[i] 만큼 insert -

multipart 라이브러리를 이용한 파일테이블에 insert

 

총 3번의 insert가 들어가서 상품정보가 등록된다.

 


3개의 테이블에 대한 VO가 필요한데,

파일 테이블의 VO는 필요없고 상품과 옵션의 VO다.

/*     */ public class ItemVO
/*     */ {
/*     */   private int item_no;
/*     */   private String item_admin;
/*     */   private String item_name;
/*     */   private String item_price;
/*     */   private String item_size;
/*     */   private String item_color;
/*     */   private int item_disc;
/*     */   private String item_content;
/*     */   private String item_imgsub;
/*     */   private Date item_date;
/*     */   private int item_star;
/*     */   private String item_catemain;
/*     */   private String item_catesub;
/*     */   private String item_subcontent;
/*     */   private String item_model;
/*     */   private String item_imgmain;
/*     */   private String[] item_option;
/*     */   private int[] item_vol;
/*     */   private String option_content;
/*     */   private String option_item_no;
/*     */   private int option_vol;
/*     */   private int option_no;
public class OptionVO {
	private int option_no;
	private String option_content;
	private int option_item_no;
	private int option_vol;

item_no ( 상품PR ) 을 기준한다.


mapper

 

	<insert id="itemInsert" parameterType="kr.co.vo.ItemVO"
		useGeneratedKeys="true" keyProperty="item_no">
		<selectKey keyProperty="item_no" resultType="int" order="BEFORE">
			SELECT
			ITEM_SEQ.NEXTVAL FROM DUAL
		</selectKey>

		INSERT INTO ITEM (ITEM_NO , ITEM_NAME , ITEM_PRICE , ITEM_SIZE, ITEM_COLOR, 
		 ITEM_CONTENT, ITEM_CATEMAIN, ITEM_CATESUB, ITEM_SUBCONTENT, ITEM_MODEL
		) VALUES (
		#{item_no} ,
		#{item_name},
		#{item_price},
		#{item_size},
		#{item_color},
		#{item_content},
		#{item_catemain},
		#{item_catesub},
		#{item_subcontent},
		#{item_model}
		)
	</insert>
	
	<insert id="itemOptionInsert" >
	INSERT INTO ITEMOPTION (OPTION_NO, OPTION_CONTENT, OPTION_ITEM_NO , OPTION_VOL 
	)VALUES(
	(SELECT NVL(MAX(OPTION_NO), 0) + 1 FROM ITEMOPTION) , #{item_option} , #{item_no} , #{item_vol}
	)
	</insert>


	<insert id="itemMainFile">
	insert into IMG (IMG_NO , IMG_ORGNAME , IMG_STRNAME , IMG_SIZE , IMG_ITEM_NO
	)VALUES(
	(SELECT NVL(MAX(IMG_NO), 0) + 1 FROM IMG), #{IMG_ORGNAME}, #{IMG_STRNAME} , #{IMG_SIZE} , #{ITEM_NO}
	)
	</insert>
    
    	<update id="itemMainImg">
	update item set ITEM_IMGMAIN = #{IMG_STRNAME} where ITEM_NO = #{ITEM_NO}
	</update>
	
	<update id="itemSubImg">
	update item set ITEM_IMGSUB = #{IMG_STRNAME} where ITEM_NO = #{ITEM_NO}
	</update>

상품등록 , 옵션등록 , 파일등록 후 상품테이블에 파일명을 update 시켜준다.

 

item_no가 필요한데 , 그러려면 먼저 아이템이 insert되어야 하기 때문에  이런 방식으로 구현했다.

 

select key를 사용해서 item_no가 등록되고 VO에 set되도록 했으며,

 

VO에 set 된 item_no를 기준으로 옵션을 등록한다.

 

 

 


service

/*    */   @Transactional
/*    */   public void itemInsert(ItemVO itemVO, MultipartHttpServletRequest multipart) throws Exception {
/* 29 */     this.masterDAO.itemInsert(itemVO);
/*    */     
/* 31 */     Map<String, Object> itemMainImg = this.fileUtils.itemMainImg(itemVO, multipart);
/* 32 */     this.masterDAO.itemMainImg(itemMainImg);
/* 33 */     this.masterDAO.itemMainFile(itemMainImg);
/*    */     
/* 35 */     Map<String, Object> itemSubImg = this.fileUtils.itemSubImg(itemVO, multipart);
/* 36 */     this.masterDAO.itemSubImg(itemSubImg);
/* 37 */     this.masterDAO.itemMainFile(itemSubImg);
/*    */     
/* 39 */     for (int i = 0; i < (itemVO.getItem_option()).length; i++) {
/* 40 */       String itemOptionContent = itemVO.getItem_option()[i];
/* 41 */       int itemOptionVol = itemVO.getItem_vol()[i];
/* 42 */       Map<String, Object> map = new HashMap<String, Object>();
/* 43 */       map.put("item_option", itemOptionContent);
/* 44 */       map.put("item_no", Integer.valueOf(itemVO.getItem_no()));
/* 45 */       map.put("item_vol", Integer.valueOf(itemOptionVol));
/* 46 */       this.masterDAO.itemOptionInsert(map);
/*    */     } 
/*    */   }

먼저 , 상품을 insert하는 itemInsert 이다.

 

그 다음 , 메인이미지와 서브이미지를 insert하고 , 로컬에 저장하는 itemMainImg 와 itemSubImg 이다.

 

multipart를 사용해서 파일의 값을 불러오고 , 로컬에 저장 후 정보를 map에 담아서 return 해야하는데

 

해당 부분은 너무 길어질 것 같아, fileUtils라는 클래스를 만들어 처리했다.

 

그에 대한 내용은 전 글에 설명했다.

  

[스프링]게시판 첨부파일 업로드 구현 설명(insert) (1) :: 간편 웹프로그래밍 (tistory.com)

 

[스프링]게시판 첨부파일 업로드 구현 설명(insert) (1)

오라클,스프링프레임워크 기준입니다. 먼저 파일추가에 필요한 테이블을 추가해준다. CREATE TABLE MP_FILE ( FILE_NO NUMBER, BNO NUMBER NOT NULL, ORG_FILE_NAME VARCHAR2(260) NOT NULL, STORED_FILE_NAME VAR..

kimfk567.tistory.com

 

그 후 , option에 대한 내용을 옵션 수 만큼 insert하는 로직이다. 

 

for문을 사용해서 배열의 수 만큼, 배열의 값을 담아 insert 한다.

 

뷰에서 같은 name값의 파라미터가 들어오면 , 컨트롤러는 자동으로 파라미터를 배열로 받아준다.

 

때문에, 배열로 받아서 처리했다.

 


Controller

  @RequestMapping(value = {"/itemInsert"}, method = {RequestMethod.POST})
  public String ItemInsert(ItemVO itemVO, MultipartHttpServletRequest multipart) throws Exception {
    logger.info("itemInsert=");
    this.masterService.itemInsert(itemVO, multipart);
    return "/master/ItemInsertView";
  }

컨트롤러에선 아이템VO로 상품 기본정보와 option의 정보를 배열로 받아온다. ( VO에 배열로 된 객체가 있다)

 

파일은 multipartHttpServletRequest로 받아서,

 

multipartFile을 이용해 name값으로 main인지 , sub인지 구별하여 처리했다.

 


View 부분이다.


						<form action="/master/itemInsert" method="post"
							name="itemInsertForm" id="itemInsertForm"
							enctype="multipart/form-data">

							<div class="tab-content">
								<!-- 상품등록 -->
								<div class="tab-pane active" id="itemInsert_1">
									<div class="form-group" style="">

										<h3>대분류</h3>
										<select class="form-control" name="item_catemain"
											id="item_catemain" title="상품 대분류">
											<option value="item">일반상품</option>
											<option value="mainpage">메인페이지</option>
											<option value="popularitem">인기상품</option>
										</select>
										<h3>소분류</h3>
										<select class="form-control" name="item_catesub"
											id="item_catesub" title="상품 소분류">
											<option value="jumper">Jumper</option>
											<option value="coat">Coat</option>
											<option value="jacket">Jacket</option>
											<option value="padding">Padding</option>
											<option value="shirts">Shirts</option>
			
										</select>
									</div>
									<hr class="divider-w mt-10 mb-20">
									<div class="form-group">
										<h3>상품명</h3>
										<input class="form-control input-lg" type="text"
											placeholder="상품명" name="item_name" id="item_name" />
									</div>
									<hr class="divider-w mt-10 mb-20">
									<div class="form-group">
										<h3>판매가</h3>
										<input class="form-control input-lg" type="number"
											placeholder="판매가 / 단위 : 원" name="item_price" id="item_price" />
									</div>
									<hr class="divider-w mt-10 mb-20">

									<div class="form-group">
										<h3>사이즈</h3>
										<input class="form-control input-lg" type="text"
											placeholder="사이즈" name="item_size" id="item_size" />
									</div>
									<hr class="divider-w mt-10 mb-20">
									<div class="form-group">
										<h3>색상</h3>
										<input class="form-control input-lg" type="text"
											placeholder="색상" name="item_color" id="item_color" />
									</div>
									<hr class="divider-w mt-10 mb-20">

									<div class="form-group">
										<h3>상품설명</h3>
										<input class="form-control input-lg" type="text"
											placeholder="상품설명" name="item_subcontent"
											id="item_subcontent" />
									</div>
									<hr class="divider-w mt-10 mb-20">

									<div class="form-group">
										<h3>모델정보</h3>
										<input class="form-control input-lg" type="text"
											placeholder="모델정보" name="item_model" id="item_model" />
									</div>
									<hr class="divider-w mt-10 mb-20">

									<!-- 상품내용 에디터 -->

									<div class="form-group">
										<h3>상품내용</h3>
										<textarea class="form-control input-lg"
											placeholder="내용을 입력하세요" name="item_content" id="item_content">
											</textarea>


								</div>

								<!-- 상품등록 끝-->


								<!--  상품옵션 -->
								<div class="tab-pane" id="itemInsert_2">


									<button id="optionAdd_btn" class="btn btn-primary mb-3"
										type="button">옵션추가</button>

									<div id="optionIndex"></div>
									<br />
									<div class="form-group mt-3">
										<input class="form-control input-lg " type="text"
											placeholder="최소 1개의 옵션이 필요합니다. ex) 100 , red /// 95 , blue "
											readonly />
									</div>

								</div>
								<!--  상품옵션 끝 -->



								<!--  상품이미지 -->
								<div class="tab-pane" id="itemInsert_3">

									<div class="form-group">
										<h3>메인이미지 ( 썸네일 )</h3>
										<input class="form-control input-lg" type="file"
											name="itemMainImg" id="itemMainImg" />
									</div>
									
									<div class="form-group">
										<h3>서브이미지 ( 썸네일에 마우스 올릴시 )</h3>
										<input class="form-control input-lg" type="file"
											name="itemSubImg" id="itemSubImg" />
									</div>
									
								
									<button class="btn btn-d btn-circle" type="button"
										onclick="fnSubmit(); return false;">상품등록</button>


								</div>
						</form>


						<!--  상품이미지 끝 -->






					</div>

	$(document).ready(function() {
		console.log('ready');

		optionAdd();
	});

	function optionAdd() {
		console.log('optionadd');
		var optionIndex = 1;
		//$("#fileIndex").append("<div><input type='file' style='float:left;' name='file_"+(fileIndex++)+"'>"+"<button type='button' style='float:right;' id='fileAddBtn'>"+"추가"+"</button></div>");
		$("#optionAdd_btn")
				.on(
						"click",
						function() {
							console.log('옵션추가');
							$("#optionIndex")
									.append(
											"  <div class='form-group'><input placeholder='옵션' class='form-control input-lg' type='text' style='float:left;' name='item_option"
													
													+ "' id='item_option'>"
													+ "<input type='number' name='item_vol' id='item_vol' placeholder='수량'>"
													+ "<button type='button' style='float:right;' id='optionDelBtn' class='btn-btn dark'>"
													+ "삭제" + "</button></div>"

									);

						});

		$(document).on("click", "#optionDelBtn", function() {
			$(this).parent().remove();

		});

	};

	function fnSubmit() {

		var email_rule = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;
		// var tel_rule = /^\d{2,3}-\d{3,4}-\d{4}$/; 전화번호용

		if ($("#item_name").val() == null || $("#item_name").val() == "") {
			alert("상품명을 입력해주세요.");
			$("#item_name").focus();

			return false;
		}

		if ($("#item_price").val() == null || $("#item_price").val() == "") {
			alert("상품가격를 입력해주세요.");
			$("#item_price").focus();

			return false;
		}

		if ($("#item_size").val() == null || $("#item_size").val() == "") {
			alert("상품사이즈를 입력해주세요.");
			$("#item_size").focus();

			return false;
		}

		if ($("#item_color").val() == null || $("#item_color").val() == "") {
			alert("상품색상을 입력해주세요.");
			$("#item_color").focus();

			return false;
		}

		if ($("#item_vol").val() == null || $("#item_vol").val() == "") {
			alert("상품수량을 입력해주세요.");
			$("#item_vol").focus();

			return false;
		}

		if ($("#item_content").val() == null || $("#item_content").val() == "") {
			alert("상품내용을 입력해주세요.");
			$("#item_content").focus();

			return false;
		}

		if ($("#item_subcontent").val() == null
				|| $("#item_subcontent").val() == "") {
			alert("상품설명을 입력해주세요.");
			$("#item_subcontent").focus();

			return false;
		}

		if ($("#item_model").val() == null || $("#item_model").val() == "") {
			alert("모델정보를 입력해주세요.");
			$("#item_model").focus();

			return false;
		}

		if ($("#item_option").val() == null || $("#item_option").val() == "") {
			alert("상품옵션을 입력해주세요.");
			$("#item_option").focus();

			return false;
		}

		if ($("#itemMainImg").val() == null || $("#itemMainImg").val() == "") {
			alert("상품썸네일사진 등록해주세요.");
			$("#itemMainImg").focus();

			return false;
		}
		
		if ($("#itemSubImg").val() == null || $("#itemSubImg").val() == "") {
			alert("상품썸네일보조사진 등록해주세요.");
			$("#itemSubImg").focus();

			return false;
		}

		if (confirm("등록하시겠습니까?")) {

			$("#itemInsertForm").submit();

			return false;
		}
	}

옵션추가 및 상품등록 전 공백검사 script 문이다.

 

 

728x90
저작자표시 (새창열림)

'SPRING > Homme Shop' 카테고리의 다른 글

[스프링] 쇼핑몰 - 상품 주문 [ 2 ]  (0) 2021.12.09
[스프링] 쇼핑몰 - 상품 주문 [ 1 ]  (0) 2021.12.08
[스프링] 쇼핑몰 - 비동기 장바구니 [3]  (1) 2021.12.08
[스프링] 쇼핑몰 - 비동기 장바구니 [2]  (1) 2021.12.08
[스프링] 쇼핑몰 - 비동기 장바구니 [1]  (6) 2021.12.08
    'SPRING/Homme Shop' 카테고리의 다른 글
    • [스프링] 쇼핑몰 - 상품 주문 [ 1 ]
    • [스프링] 쇼핑몰 - 비동기 장바구니 [3]
    • [스프링] 쇼핑몰 - 비동기 장바구니 [2]
    • [스프링] 쇼핑몰 - 비동기 장바구니 [1]
    간펴니
    간펴니
    개발공부 기록하는 곳

    티스토리툴바