10/06/2018

스프링 쇼핑몰 만들기 #8. 상품등록하기

스프링 쇼핑몰 만들기

카테고리가 정상적으로 나오니, 이제 상품등록을 해야합니다. 상품등록이라고 했지만, 게시판의 게시물 작성과 다르지 않습니다.

CRUD, 즉 Create(생성), Read(읽기), Update(갱신), Delete(삭제)의 연속입니다.

register.jsp에서 폼 태그 <from> 에 코드를 추가합니다.

<form role="form" method="post" autocomplete="off">

<div class="inputArea"> 
 <label>1차 분류</label>
 <select class="category1">
  <option value="">전체</option>
 </select>

 <label>2차 분류</label>
 <select class="category2" name="cateCode">
  <option value="">전체</option>
 </select>
</div>

<div class="inputArea">
 <label for="gdsName">상품명</label>
 <input type="text" id="gdsName" name="gdsName" />
</div>

<div class="inputArea">
 <label for="gdsPrice">상품가격</label>
 <input type="text" id="gdsPrice" name="gdsPrice" />
</div>

<div class="inputArea">
 <label for="gdsStock">상품수량</label>
 <input type="text" id="gdsStock" name="gdsStock" />
</div>

<div class="inputArea">
 <label for="gdsDes">상품소개</label>
 <textarea rows="5" cols="50" id="gdsDes" name="gdsDes"></textarea>
</div>

<div class="inputArea">
 <button type="submit" id="register_Btn" class="btn btn-primary">등록</button>
</div>

</form>

<div class="inputArea"> 를 이용해 각 입력요소를 묶어두었습니다. 이렇게하면 나중에 CSS를 적용할 때 일괄적으로 작업할 수 있습니다.

각 인풋(input)의 아이디와 네임은 상품VO인 GoodsVO를 참고하여 만들었으며, GoodsVO는 tbl_goods를 참고하여 만들었습니다. (테이블, VO 생성)

꼭 테이블과 VO와 인풋의 이름이 같을 필요는 없습니다. 하지만 모두 같게할 경우 알아보기도 쉬울뿐더러 역할에도 맞고, 새로운 이름을 만들어야하는 귀찮음도 없습니다.

프로젝트를 실행해보면 투박한 디자인의 입력란이 보입니다.

아직 매퍼-DAO-Service-컨트롤러 작업을 하지 않았기 때문에 등록은 안됩니다.

먼저 직접 쿼리를 작성/실행하여 임시 데이터를 추가해봅니다.

상품등록시 이미지 파일을 업로드하는 기능은 없기 때문에, gdsImg는 입력하지 않았으며 그에 따라 null이 표시되고 있습니다.

그외엔 모두 정상적으로 입력된걸 확인할 수 있습니다. 이 쿼리문을 그대로 사용하면 될 것 같습니다.

매퍼에 쿼리를 추가합니다.

<!-- 상품 등록 -->
<insert id="register">
 insert into tbl_goods (gdsNum, gdsName, cateCode, gdsPrice, gdsStock, gdsDes)
     values (tbl_goods_seq.nextval, #{gdsName}, #{cateCode}, #{gdsPrice}, #{gdsStock}, #{gdsDes})
</insert>

DAO와 Service도 작업합니다.

현재는 쿼리문만 작동되면 되기 때문에 별다른 코드는 없습니다.

컨트롤러에도 상품등록용 POST 메서드를 추가합니다.

역시 별다른 코드는 없으며, 등록이 성공적으로 되었다면 return "redirect:/admin/index"; 로 인해 관리자 화면의 처음으로 이동하게 됩니다.

이제 실제로 등록이 되는지 테스트해봅니다.

500에러가 발생했고, 내용을 보니 '부적합한 열 유형'이라는게 나왔습니다.

매퍼까지는 데이터가 전해졌지만, null이 전달되어서 에러가 발생했습니다. null 데이터를 받은건 cateCode(카테고리 코드)입니다. 당연한 얘기지만, 카테고리 구성은 제대로 했으나 이름(name) 부여를 하지 않았기 때문에 생긴 에러입니다.

여기서 문제가 되는게, 지금 카테고리는 1차 분류와 2차 분류로 두가지로 구분되며, 무기 카테고리만 1차/2차 분류가 되고 다른 카테고리들은 1차 분류만 가능합니다. 그리고 카테고리 코드는 하나만 등록할 수 있습니다.

이 문제를 해결할 방법은 많은데, 저는 카테고리를 구성할 때 카테고리 코드를 부여하는 방법으로 하겠습니다.

먼저 2차 분류의 셀렉트 박스에 이름(name)속성을 부여합니다.

그리고 register.jsp의 스크립트 부분에 cate2Select.append("<option value='" + selectVal + "'>전체</option>"); 를 추가합니다.

selectVal는 '현재 선택한 1차 분류의 코드'이므로 2차 분류의 기본선택지인 '전체'에도 같은 코드가 적용됩니다.

2차 분류의 '전체' 카테고리가 1차 분류와 같은 코드로 되어있는걸 확인할 수 있습니다.

제대로 등록되는지 확인하기 위해 테스트용 데이터를 입력하고 등록 버튼을 클릭합니다.

등록 버튼을 클릭하자 관리자 화면의 처음으로 이동했습니다.

테이블을 확인해보니 정상적으로 등록된걸 확인할 수 있습니다.

이제 간단한 CSS를 추가합니다.

<style>
.inputArea { margin:10px 0; }
select { width:100px; }
label { display:inline-block; width:70px; padding:5px; }
label[for='gdsDes'] { display:block; }
input { width:150px; }
textarea#gdsDes { width:400px; height:180px; }
</style>

위에 있는 스타일시트 <style> ~ </style> 과 구분되도록 만들어뒀는데, 이후에 각 스타일은 파일로 분류할것이기 때문에 미리 구분해두는것이며 같은곳에 입력해도 상관없습니다.

크기와 여백정도만 수정해서 정렬시켰으며, 등록 버튼은 부트스트랩의 버튼 클래스 btn btn-primary를 부여했습니다.

게시물 수정
  1. 작성자가 댓글을 삭제했습니다.

    답글삭제
  2. 안녕하세요

    게시판과는 무관한 질문이지만 여쭙고 싶은게 있습니다.
    6개월 수업듣고 신입으로 들어가려고하는데 , 게시판 만들기는 어렵지않은데 쇼핑몰 만들기가 너무 어렵네요
    쇼핑몰 만들기정도 는 쉽게 만들수 있어야 회사 들어가기 수월할까요..?

    답글삭제
    답글
    1. 쇼핑몰이라면, 혹시 이 블로그의 쇼핑몰 말씀하시는건가요?
      이런건.. 실력 좋은 사람이 설명하면 쉬운데, 제대로 못하는 사람이 설명해서 어려운겁니다ㅠㅠㅋ

      가장 큰 문제는.. 코드를 만들어가며 설명을 해야하는데
      만들어진 코드를 통채로 붙이고 설명해서 난잡/난해하다는것이죠ㅠㅠ;

      결론적으로 CRUD+@만 무난히 하시면 됩니다. CRUD는 게시판으로도 충분하고, @부분은 응용하거나 라이브러리에 대한 이해정도로 보시면 되겠습니다.

      교육과정에서 배운것과 실제 업무에서 배운 내용은 여러모로 차이가 크기 때문에.. 어지간히 우수한 평가를 받더라도 넓은 시야와 어느정도 깊이 있는 지식이 없으면 낯설고 버둥버둥(?) 거릴 수 밖에 없습니다.

      물론 신입이니까 그것이 당연한겁니다.
      입사하자마자 혼자 프로젝트 뚝딱뚝딱 버그 없이 만들고 기능 요청 날아오면 냉큼 구현하고 이러는건 아니니까요.

      개인적인 의견으로 좀더 공부하고 취직하는것보단, 가능한 빨리 입사하는걸 추천드립니다. 단, 흔히 말하는 '보도방'은 제외하고요. (경력 허위 조작, 신입 홀로 파견, 월급을 제대로 안주는 등등 문제가 많습니다)

      배우는것과 현업은 차이가 있을 수 밖에 없기 때문에, 현업을 최대한 빨리 접하는게 좋지요.

      삭제
    2. 찾아봐도 막무가내 SI가많은것 같구 , 이번에 면접본곳은 대졸 연봉이 2200이고 ,, 심란하네요..
      답변 정말 감사드립니다..

      삭제
    3. 아무래도 정상적인곳은 입사후 퇴사를 하지 않다보니 그만큼 모집을 덜하게 되고, 보도방은 퇴사를 엄청나게 하니까 자주 보일 수 밖에 없습니다만, 분명 보도방이 아닌곳도 존재합니다.
      전 처음에 가산/구로 디지털 단지가 메타라고해서 그쪽만 알아봤는데, 보도방이 많더라구요-_-;

      지원하시기 전 어느정도 거를 수 있는 방법이라면

      1. 회사 주소를 로드뷰로 보기
      - 직원수 100명이라는데, 로드뷰로 보니 건물이 엄청 작다거다하면 파견만 하는 업체입니다.
      - 그리고 회사의 과거 이름을 알 수 있기도합니다.
      - 회사명을 바꿨다면, 대부분 경력 위조로 인해 바꾼 경우가 대부분입니다.

      2. 잡플래닛등의 평가 사이트 확인 (https://www.jobplanet.co.kr/)
      - 기업 정보와 면접 후기등을 볼 수 있습니다.
      - 자기가 기업 정보나 면접 후기를 작성하면, 일정기간 무료로 볼 수 있기 때문에 면접본 곳이 있으면 작성하시는게 여러모로 좋습니다.

      3. 자본금이 지나치게 작거나, 인원수가 지나치게 적은 경우
      - 자본금 몇백~몇천으로 시작하거나, 인원수가 3~5명정도라면... 이곳 역시 파견업일 가능성이 높습니다.

      4. IT노조 확인 (http://www.itunion.or.kr/)
      - 악덕업체는 IT노조에서 볼 수 있습니다.


      '보도방'.. 그러니까 경력 위조라던가, 신입이라고 교육비를 받아간다던가, 월급 200준다면서 신입이니 자격증이 없다니 신용할 수 없다느니 하는 이유로 월 80을 준다던가 하는곳이 많아서 그렇지..

      '파견 업체'가 자체가 안 좋은건 아닙니다. 멀쩡한 파견 업체도 있어요ㅠ


      아무쪼록 좋은 결과 있기를 바라겠습니다.

      삭제
    4. 정말 감사합니다..

      삭제
    5. 언제나 참고가 됩니다 너무 감사합니당

      삭제
  3. 익명4/24/2019

    cate2Select.append("<option value='" + selectVal + "'>전체</option>")
    라는 코드를 보면 작은 따옴표 안에 큰 따옴표를 사용했는데요
    굳이 작은 따옴표를 사용하지 않고
    cate2Select.append("<option value=" + selectVal + ">전체</option>")
    로 사용해도 되지 않나요?
    아니면 작은 따옴표의 용도가 따로 있는건지 궁금합니다

    답글삭제
    답글
    1. 안녕하세요?

      selectVal의 값이 0 이라는 가정하에
      "<option value='" + selectVal + "'>전체</option>" 이렇게 코딩을 했으면
      결과는 <option value='0'>전체</option>가 됩니다.

      이번엔
      "<option value=" + selectVal + ">전체</option>" 이렇게 코딩을 했으면
      결과가 <option value=0>전체</option>가 됩니다.

      속성값은 쌍따옴표 또는 홀따옴표로 감싸서 사용하는게 기본적인 문법입니다. 물론, 사용하지 않는다고해서 에러가 발생하는건 아닙니다.

      여기서 홀따옴표를 사용한 이유는, 쌍따옴표를 사용하게될 경우 자바스크립트내의 문자열로 끝나기 때문입니다.

      주의해야할점은, 속성값이 여러개인 속성입니다. 예를들어서 클래스가 2개 이상의 값을 가지고 있는데, 이때 각 속성값을 구분하는건 공백문자입니다.

      <div class="a1 b1 c1 d1" style="color:#000;"> 이런식으로 클래스가 2개 이상일 경우 쌍따옴표 또는 홀따옴표로 감싸우면 이상이 없으나

      <div class=a1 b1 c1 d1 style="color:#000;"> 이렇게 쌍따옴표나 홀따옴표가 없다면, 브라우저가 속성과 속성값을 구분할 수 없기 때문에 에러가 발생하거나 정상적으로 동작하지 않을 수 있습니다.

      삭제
  4. 혹시 ㅠㅠ 버튼으로 form 안에 입력받은 정보를 디비에 넣는 부분에 대한 설명은 없을까요 ㅠ ㅠ 버튼 눌러도 아무 동작을 안하네요.. 깃허브에 올려주신 코드를 봐도 잘 모르겠구요 ㅠ ㅠ

    답글삭제
  5. 보시는 분들께서는 sequence(시퀀스) 안 만드셨으면 만드시고 commit하세요

    답글삭제
  6. 안녕하세요. 엄청 도움이 되고 있습니다. 진행 중에 상품등록에서 405에러가 떠서 컨트롤러 쪽에서 @RequestMapping(value = "/goods/register", method = {RequestMethod.GET, RequestMethod.POST}) 이렇게 get post 둘다 받아서 오류를 해결하려 했는데 이래도 Request method 'POST' not supported 405 에러가 뜨네요. 혹시 해결방안 없을까요?

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      get과 post모두 받으실땐 method 자체를 비워주시면 될거라 생각합니다.


      기능적으로 차이가 없도록 잘 만들더라도
      누가봐도 어렵지 않게 파악하기 위해서 get과 post를 구분해두시는걸 추천합니다.

      삭제
    2. 익명5/30/2020

      안녕하세요 질문 등록자입니다. 메소드를 비워도 해결이 안되어서 다시 질문을 올립니다. 제가 카테고리 기능은 필요치 않아 제외하여 진행하였는데 이 부분 때문에 상품 등록에서 405에러가 뜨는것 인지 질문드립니다.

      삭제
  7. 익명6/10/2020

    안녕하세요. 공부중인 학생입니다. 제가 진행하다가 막혔는데 상품 등록을 하면 ORA-02291: 무결성 제약조건(ADMIN.FK_GOODS_CATEGORY)이 위배되었습니다- 부모 키가 없습니다. 이렇게 부모키가 없어서 등록이 안된다고 하네요 그래서 해결방안이 있는지 질문드려봅니다.

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      본문에 있는 방식으로 카테고리를 작성해야할 경우..

      카테고리 참조 코드(cateCodeRef)는 null이거나, 카테고리 코드(CateCode)에 등록된것만 사용할 수 있습니다.
      만약 부모키가 없다는 에러가 나왔을 경우, 카테고리 참조 코드가 잘못 입력되어있을 가능성이 높습니다.

      #7. 카테고리 구성쪽에 테이블에 대한 설명이 나와있으니.. 이미 보셨을테지만; 한번 더 보시기 바랍니다ㅠㅠ

      삭제
  8. 안녕하세요 항상 잘 보고있습니다.
    제가 mariadb로 연동해서 만들고있는데 Mapper쪽에서 nextval 이라는 함수는 없더군요
    해결하는 방법이 있을까요 ?

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      nextval은 오라클에서 시퀀스의 다음값을 호출하는건데
      말씀하신 mariadb에서는 auto_increment를 사용하시면 됩니다...만 이미 아래에 해결하셨네요.
      고생하셨습니다.

      삭제
  9. 찾았네요 ...ㅎㅎ
    mariadb로 사용하시는 분들은


    insert into tbl_goods (gdsNum, gdsName, cateCode, gdsPrice, gdsStock,gdsDes)
    values (NEXTVAL(tbl_goods_seq), #{gdsName}, #{cateCode},#{gdsPrice}, #{gdsStock}, #{gdsDes})

    로 작성하시면 될것같습니다.

    답글삭제
  10. impl 파일에 inject는 꼭 필요한 건가여??

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      구현부(impl)에 있는 @inject의 경우, 해당 요소를 주입하기 위함이므로 꼭 필요합니다.
      단, 주입해놓고 쓰지 않는 경우(즉, 변수를 선언만하고 사용하지 않은 경우와 비슷)는 해당 요소를 삭제하셔도 됩니다.

      삭제
  11. 익명3/23/2021

    안녕하세요. 잘 보고있습니다. 혹시 register.jsp파일에 name도 다 주고 script부분에도 SelectVal까지 다 입력했는데,
    계속 Could not set parameters for mapping: ParameterMapping{property='gdsName', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'} 라는 오류가납니다ㅠㅠ 해결방법이 있을까요??

    답글삭제
    답글
    1. 익명3/23/2021

      해결했습니다~

      삭제
    2. 익명8/15/2022

      혹시 어떻게 해결하셨나요ㅜㅜ저도 같은 오류가 떴는데 해결이 안되네요....ㅠ

      삭제
  12. 익명5/22/2021

    안녕하세요~ 게시판과 쇼핑몰글 보면서 여기까지 왔습니다!!
    다름 아니라 등록도 되고 그 다음 index로도 이동도 잘 되는데
    문제는 디비에 제가 입력한 값은 나오지 않고, 디비에서 직접 집어넣었던 테스트 값들이 계속 출력이 되더라고요ㅠㅠ
    무슨 문제인지 아실까요..?? ㅠㅠ 오류도 뜨지 않아서 정말 모루겠슴당..

    답글삭제
    답글
    1. 익명5/22/2021

      혹시 해서 마리아디비에서 직접 넣어보니 오류가 뜨더라고요.. 외래키 문제 일까요.. ㅠ

      SQL 오류 (1452): Cannot add or update a child row: a foreign key constraint fails (`board`.`tbl_goods`, CONSTRAINT `fk_goods_category` FOREIGN KEY (`cateCode`) REFERENCES `goods_category` (`cateCode`))uery

      삭제
    2. 익명5/22/2021

      헉 외래키 검사를 비활성했더니 디비에서 직접 넣는건 되는데
      아직도 페이지에서 등록하면 디비에서 테스트했던 값들로 나오네요 ㅠ

      삭제
    3. 안녕하세요? 방문해주셔서 감사합니다.

      외래키를 제거하면 안됩니다. 외래키 없이 작업하는 경우도 있지만, 이 블로그에있는건 입문에 가까운 내용이기 때문에 기본적으로 외래키등의 선택적인 요소(?)라도 유지해주셔야합니다.

      1452에러는 참조하려는 키가 실제로 존재하지 않을 경우 발생하는 에러인데, 데이터를 확인하고 올바르게 데이터가 입력되고 있는지 확인하셔야할 것 같습니다.

      삭제
  13. 익명8/15/2022

    안녕하세요 덕분에 공부 잘 하고있습니다 !!!그런데 Could not set parameters for mapping: ParameterMapping{property='gdsName', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'} 오류가 계속 뜹니다.. 이유를 모르겠습니다 알려주실수있으실까요ㅠㅠ

    답글삭제
  14. 안녕하세요 덕분에 공부 잘 하고 있습니다. 다름아니라 insert into 부분에 따라치면 SQL 오류: ORA-02289: sequence does not exist
    02289. 00000 - "sequence does not exist"
    *Cause: The specified sequence does not exist, or the user does
    not have the required privilege to perform this operation.
    *Action: Make sure the sequence name is correct, and that you have
    the right to perform the desired operation on this sequenc
    이렇게 에러가 발생하더라고요 시퀀스 가 존재하지않는다는데 따로 어떻게 지정해야 하나요?

    답글삭제
    답글
    1. 아 해결했습니다. tbl_good_seq.nextval 가 뭔가했는데 시퀀스 테이블을 tbl_good_seq로 하신다음에 insert 문에 넣으신거였군요. 한줄기 빛과 같은 포스팅입니다.!!

      삭제