-
학원 day52. merge into문, 장바구니 리스트 삭제하기, include, 암호화기록 2022. 11. 18. 01:29
Merge into
- 하나의 SQL문으로 INSERT, UPDATE, DELETE 작업을 수행할 수 있다.
- 형식
MERGE INTO 테이블명
USING DUAL
ON (컬럼명 = 값 AND 컬럼명 = 값) -- 이 조건에 맞는 행이 있는지 확인
WHEN MATCH THEN
UPDATE
SET 컬럼명 = 값
WHEN NOT MATCHED THEN
INSERT (컬럼명, 컬럼명, 컬럼명)
VALUES (값, 값, 값);
** insert에 into 안붙이는거 주의!! 테이블명은 merge into에만 작성하고 아래에는 적지 않음!
<carts.xml> <insert id="insertCartItem" parameterClass="com.sample.vo.CartItem"> merge into sample_board_book_cart_items using dual on (book_no = #bookNo# and user_id = #userId#) // 이 조건에 맞는 행이 존재하면 when matched then update set item_amount = item_amount + 1, // 수량을 1 추가 item_updated_date = sysdate when not matched then insert (item_no, book_no, user_id) // 존재하지 않는다면 insert values (sample_carts_seq.nextval, #bookNo#, #userId#) </insert>
장바구니에 상품을 담을 때 insert문 대신에 merge into를 사용할 수 있다.
기존 장바구니에 담겨져 있는 상품을 담으면 수량에 1추가(update), 담겨있지 않으면 새로 insert하는 쿼리이다.
** merge into가 생각나지 않으면 select문과 update문을 써도 된다.
delete작업 수행하기
item_no, book_no는 화면에 표현되지는 않지만 select문에 적어야 한다.
item_no는 primary key 제약조건이 걸려있는 행을 대표하는 값이다. 따라서, 장바구니 리스트에서 행을 선택하거나 삭제하거나 구매하는데 쓰일 수 있다.
book_no는 책제목 링크를 걸때 책번호로 전달해야 하기 때문에 필요하다.
책번호나 사용자 아이디로는 같은 값을 가진 행이 있을 수 있어서 특정 행을 삭제하는데 쓰일 수 없다.
<logincheck.jsp>
- 로그인 확인 코드는 자주 쓰는 코드라서 logincheck.jsp라는 이름으로 별도로 파일을 만들어서 어디에든 사용할 수 있도록 한다.
- 다른 jsp에서 사용할 때 상단에 <%@ include file="../common/logincheck.jsp" %> 코드를 붙여주면 된다.
<% User loginUser = (User) session.getAttribute("loginedUser"); if (loginUser == null) { response.sendRedirect("/web-board/user/loginform.jsp?error=deny"); // 어디에 포함될지 몰라서 절대경로로 적는다. return; } %>
<deleteItems.jsp>
- 정적 include를 사용했다.
- 같은 이름의 입력값이 여러개일 경우, request.getParameterValues("itemNo")를 사용한다.
기존 request.getParameter()로는 값을 하나밖에 담지 못한다.
request.getParameterValues메소드가 실행되면 String[] 배열이 반환된다.
- 향상된 for문을 사용해서 itemNo에 해당하는 장바구니 아이템을 삭제한다.
<%@ include file="../common/logincheck.jsp" %> <% // 입력폼에서 체크한 체크박스의 값을 요청객체에서 조회하기 String[] values = request.getParameterValues("itemNo"); // 체크된 아이템이 없으면 values는 null이다. values가 null이면 장바구니리스트를 재요청하는 URL을 응답으로 보낸다. if(values == null) { response.sendRedirect("list.jsp"); return; } // CartItemDao객체를 생성하고, 아이템 번호에 해당하는 장바구니 아이템을 삭제하는 수행문을 반복실행한다. CartItemDao cartItemDao = new CartItemDao(); for (String value : values) { int itemNo = StringUtils.stringToInt(value); cartItemDao.deleteCartItemByNo(itemNo); } // 재요청 URL을 응답으로 보낸다. response.sendRedirect("list.jsp"); %>
<list.jsp>
- form 형식 안에 button type="submit"이 있어야 한다. submit되면 deleteItems.jsp로 체크박스에서 체크한 값들이 제출된다.
- 체크박스, 라디오버튼은 사용자가 체크한 것만 값이 제출된다.
<p>장바구니 목록을 확인하세요.</p> <form method="get" action="deleteItems.jsp"> <table class="table"> <colgroup> <col width="5%"> <col width="10%"> <col width="*"> <col width="10%"> <col width="15%"> <col width="15%"> <col width="10%"> </colgroup> <thead> <tr> <th><input type="checkbox"></th> <th></th> <th>제목</th> <th>수량</th> <th>가격</th> <th>구매가격</th> <th></th> </tr> </thead> <tbody> <% if (dtoList.isEmpty()) { %> <tr> <td colspan="7" class="text-center">장바구니에 저장된 책이 없습니다.</td> </tr> <% } else { for (CartItemDto dto : dtoList) { %> <tr class="align-middle"> <td><input type="checkbox" name="itemNo" value="<%=dto.getItemNo() %>" /></td> <td><img src="../resources/images/<%=dto.getImage() %>" class="img-thumbnail"></td> <td><a href="../book/detail.jsp?no=<%=dto.getBookNo() %>" class="text-decoration-none"><%=dto.getTitle() %></a></td> <td><%=dto.getAmount() %> 권</td> <td> <strong class="text-danger"><%=StringUtils.numberToText(dto.getDiscountPrice()) %> 원</strong> <small>(<%=StringUtils.numberToText(dto.getPrice())%> 원)</small> </td> <td><strong class="text-danger"><%=StringUtils.numberToText(dto.getAmount()*dto.getDiscountPrice()) %> 원</strong></td> <td> <a href="deleteItems.jsp?itemNo=<%=dto.getItemNo() %>" class="btn btn-secondary btn-sm">삭제</a> <a href="" class="btn btn-primary btn-sm">구매</a> </td> </tr> <% } } %> </tbody> </table> <div class=""> <a href="clear.jsp" class="btn btn-secondary btn-sm" >전체 삭제</a> <button type="submit" class="btn btn-secondary btn-sm" >선택 삭제</button> <a href="../book/list.jsp" class="btn btn-outline-primary btn-sm float-end">쇼핑계속</a> </div> </form>
값을 전달하는 방법, 서버로 요청파라미터를 보내는 방식은 3가지가 있다.
첫번째방식인 URL에 쿼리스트링을 붙여 보내는 방식은 값이 결정되어 있는 경우만 사용가능하다.
checkbox는 사용자가 뭘 고를지 모르니까 번호를 미리 넣어놓을 수 없다.
따라서, 값이 결정되어 있지 않기 때문에 form태그 get방식을 사용해야 한다. (제출할 때에도 a 태그로 링크가 아닌 button이어야 한다. 그래야 form 안에 있는게 제출이 된다.)
변경, 수정 작업을 할 때에는 전달해야될 값이 많기 때문에 주로 post방식을 쓰지만,
체크박스로 전달하는 건 값이 많지 않기 때문에 get방식을 주로 사용한다.
input필드나 textarea 등은 값이 있든 없든 무조건 제출되지만 체크박스와 라디오버튼은 선택한 것만 제출된다.
체크박스와 라디오버튼은 사용자가 고르기만 하기 때문에 값(value)이 미리 설정되어 있어야 한다.
include방식 2가지 (Static, Dynamic)
정적 include (Static include)
<%@ include file="header.jsp" %>
- home.jsp가 자바코드로 변환될 때, include한 header.jsp의 소스코드가 그대로 home_jsp.java에 포함된다. (두개의 jsp파일이 하나의 자바파일이 된다.) 따라서, header.jsp에서 선언한 변수를 home.jsp에서 사용할 수 있다.
* 변수 중복선언에 주의해야 한다. (header.jsp에서 user라는 변수를 선언했다면, home.jsp에서 user로 변수를 선언하면 안된다.)
동적 include (Dynamic include)
<jsp:include page="header.jsp"/>
- header.jsp와 home.jsp가 각각 별도의 java파일로 변환되고,
home_jsp.java코드에서 header.jsp를 include하는 메소드가 실행된다.
(실행 제어권이 header.jsp로 이동했다가 돌아온다.)
* 변수이름 충돌을 신경쓸 필요가 없다.
* header.jsp에 정의된 변수를 home.jsp에서 사용할 수 없다. (메소드 안에 선언된 변수는 해당 메소드 안에서만 사용할 수 있기 때문에 변수가 공유되지 않는다.)
=> 변수충돌을 신경쓰고 싶지 않을 때 dynamic include를 쓰는게 유리하고, header.jsp의 변수를 쓰고 싶을 때는 static include를 써야한다. 따라서, dynamic include는 로그인했는지 확인만 하고 이후에 사용자정보로 다른 로직을 처리할 수는 없지만 static include는 사용자정보(ex.user)로 다른 로직을 처리할 수 있다.
암호화
Apache Commons에서 Codec(commons-codec-1.15)을 다운받는다. 다운받은 파일안의 commons-codec-1.15jar를 복사해서 이클립스 WEB-INF/lib폴더에 붙여넣기한다.
Apache Commons는 재사용가능한 자바 컴포넌트를 설계하는 것을 목표로 하는 프로젝트이다.
* 컴포넌트 : 컴퓨터는 하드디스크, 모니터, 마우스, CPU, 키보드 등으로 구성되어 있는데 이러한 부품들은 재사용가능한 부품들이다. 재가공할 필요없이 다른 사람 컴퓨터에 꽂아서도 사용할 수 있다. 설계 목적에 맞는 특별한 기능들을 제공해준다.
register.jsp에 아래 코드를 추가한다.
String secretPassword = DigestUtils.sha256Hex(password);
user.setPassword(secretPassword);
계정의 비밀번호가 같다면 암호화된 비밀번호도 같다.
암호화된 비밀번호로 원래 비밀번호를 알 수는 없지만, 사람들이 자주 쓰는 비밀번호 조합을 암호화한 비밀번호와 같은 암호화된 비밀번호를 쓰는 계정을 해킹할 수는 있기 때문에 비밀번호만 가지고 암호화하면 안되고 소금을 쳐야 한다.
다음과 같이 코드를 변경한다.
String salt = id + email;
String secretPassword = DigestUtils.sha256Hex(salt+password);
같은 비밀번호를 사용해도 소금을 친 암호화된 비밀번호는 서로 다르게 암호화된다.
login.jsp
codec
- 텍스트 데이터나 바이너리 데이터를 인코딩/디코딩한다.
- 인코딩
원본데이터 -> 변환된 데이터
- 디코딩
변환된 데이터 -> 원본 데이터
DigestUtil
- 단방향 암호화알고리즘을 사용해서 평문을 암호문으로 변환한다.
- 인코딩만 가능
'기록' 카테고리의 다른 글
학원 day54. 스트림, 첨부파일 다운로드, 파일에 텍스트 기록 (0) 2022.11.21 학원 day53. 서블릿, 필터, 첨부파일 업로드 (0) 2022.11.18 학원 day51. namespace, pagination, 주소표기법, 장바구니 기능 (0) 2022.11.17 학원 day50. 회원가입, 로그인/로그아웃, 게시글 수정/삭제 (0) 2022.11.15 학원 day49. 게시판 리뷰 기능, 쿠키/세션, JSP 주요객체 (0) 2022.11.14