20220822_mon
데이터 조회 후 자바로 데이터를 가져오는 방법
- 1. 조인,서브쿼리 등을 사용하지 않는 쿼리문(기본-단일 테이블만 조회)
- 2. 조인,서브쿼리가 포함되는 조회 쿼리문(3가지형태로 코드를 구현 가능)
-> ex)상품-이미지 테이블 2개이상 테이블 조회..
2. 조인,서브쿼리가 포함되는 조회 쿼리문방식
- 2-1) 디비 자체기능은 VIEW를 활용하는 방법
- 2-2) Mybatis를 활용하는 방법(Mybatis의 resultMap을 어떻게 활용할 것인가)
-> Mybatis은 ServiceImpl에서 sqlSession 사용하는 것..
- 방법 1)기존 resultMap에 새로운 컬럼을 하나 추가하는 방법
ex)shop_0810프로젝트_test-mapper.xml 에서..<resultMap type="dto.ItemDTO" id="item"> <id column="ITEM_CODE" property="itemCode"/> <result column="ITEM_NAME" property="itemName"/> <result column="ITEM_PRICE" property="itemPrice"/> -> 기존 resultMap에 새로운 컬럼을 하나 추가 <result column="ATTACHED_NAME" property="attachedName"/> </resultMap> <!-- 상품목록조회 --> <select id="selectItemList" resultMap="item"> SELECT ITEM_CODE , ITEM_NAME , ITEM_PRICE , ATTACHED_NAME (-> 원래없던 컬럼을 조회해야할 때) FROM ITEM </select>
- 방법 2)테이블 관계에 따라 resultMap에서 association,collection을 추가하는 방법.
SHOP.sql
test- mapper.xml
<mapper namespace="testMapper">
<resultMap type="dto.PersonDTO" id="person">
<id column="JUMIN" property="jumin"/>
<result column="NAME" property="name"/>
<result column="AGE" property="age"/>
경력정보는 위의 testMapper의 컬럼들과 다르게 문자열 자료형이 아니다!
여러 자료형이 담긴 클래스형 자료형이다
(1:1)<association property="careerDTO" resultMap="career"/>
->컬럼은 없다. property에는 careerDTO라는 이름으로 담아오겠다.
(1:N)<collection property="certiList" resultMap="certi"/>
</resultMap>
조회한 쿼리문에서
NAME,AGE 컬럼들은 위에 personDTO에 담아서 온다.
하지만 그 밖에 없는 컬럼들은 어떻게 가져오는가?
COMPANY,WORK_DAY 컬럼들은 밑에 있는 careerDTO에 담아서가져온다.
<select id="selectList" resultMap="person">
SELECT NAME
, AGE
, COMPANY
, WORK_DAY
//사람테이블의 주민번호 조회(조인)
, TEST_PERSON.JUMIN
FROM TEST_PERSON, TEST_CAREER
WHERE TEST_PERSON.JUMIN = TEST_CAREER.JUMIN
</select>
<resultMap type="dto.CareerDTO" id="career">
<id column="CAREER_NUM" property="careerNum"/>
<result column="COMPANY" property="company"/>
<result column="WORK_DAY" property="workDay"/>
<result column="JUMIN" property="jumin"/>
</resultMap>
<resultMap type="dto.CertiDTO" id="certi">
<id column="CERTI_NUM" property="certiNum"/>
<result column="CERTI_NAME" property="certiName"/>
<result column="CERTI_DATE" property="certiDate"/>
<result column="JUMIN" property="jumin"/>
</resultMap>
<select id="selectList" resultMap="person">
SELECT NAME
, AGE
, COMPANY
, WORK_DAY
, TEST_PERSON.JUMIN
FROM TEST_PERSON, TEST_CAREER
WHERE TEST_PERSON.JUMIN = TEST_CAREER.JUMIN
</select>
<select id="selectList2" resultMap="person">
SELECT NAME
, AGE
, CERTI_NAME
, CERTI_DATE
, TEST_PERSON.JUMIN
FROM TEST_PERSON,CERTI
WHERE TEST_PERSON.JUMIN = CERTI.JUMIN
</select>
- PersonDTO 를 이해를 위해 그림으로 그린다면?
- DB 쿼리문 조회할 때
- 만약 어느 한사람이 자격증을 3개 가지고있다면? ( 위의 쿼리 조회 결과 중 '김자바'의 경우)
PersonDTO
-jumin (111)
-name (김자바)
-age (20)
-certiList(
certiDTO(certiName[정처기],certiDate[2020년5월],...)
,certiDTO(certiName[정처기],certiDate[2020년6월],...)
,certiDTO(certiName[정처기],certiDate[2020년7월],...)
)
- Q.여기서 이 사람의 이름 값을 가져오고 싶다면?
personDTO.getName(); -> '김자바'
- 하지만, 주의 할 점!
Q. 첫번째 자격증의 취득날짜 데이터값을 가져오고 싶다면?
personDTO.getCertiList().getCertiDate(); -> X
personDTO.getCertiList().get(0).getCerciDate(); -> o
- 뷰가 아닌 이 방법들을 사용하는 이유?
PersonDTO 하나만 있으면 조회된 데이터 모두 가져와서 사용할 수 있기 때문에
실습내용
- 장바구니 기능에서 같은 상품끼리는 묶고 수량까지 합하여 장바구니목록페이지에 구현하기
@WebServlet("*.ca")
public class CartController extends HttpServlet {
private static final long serialVersionUID = 1L;
private CartService cartService = new CartServiceImpl();
public CartController() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doProcess(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doProcess(request, response);
}
protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//한글 인코딩 처리
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
String requestURI = request.getRequestURI();
String contextPath = request.getContextPath();
String command = requestURI.substring(contextPath.length());
System.out.println("command = " + command);
String page = "jsp/template/template.jsp";
boolean isRediect = false;
String contentPage = "";
//장바구니 상품등록
if(command.equals("/insertCart.ca")) {
String itemCode = request.getParameter("itemCode");
int putCnt = Integer.parseInt(request.getParameter("putCnt"));
//로그인한 회원의 장바구니를 가져온다.(세션사용)
HttpSession session = request.getSession();
MemberDTO loginInfo = (MemberDTO)session.getAttribute("loginInfo");
String memId = loginInfo.getMemId();
CartDTO cartDTO = new CartDTO();
cartDTO.setPutCnt(putCnt);
cartDTO.setItemCode(itemCode);
cartDTO.setMemId(memId);
cartService.insertCart(cartDTO);
page = "jsp/cart/cart_result.jsp";
}
//장바구니 목록 페이지
else if(command.equals("/cartList.ca")) {
HttpSession session = request.getSession();
MemberDTO loginInfo = (MemberDTO)session.getAttribute("loginInfo");
List<CartDTO> cartList= cartService.selectCartList(loginInfo.getMemId());
request.setAttribute("cartList", cartList);
contentPage = "cart/cart_list.jsp";
}
request.setAttribute("contentPage", contentPage);
if(isRediect) {
response.sendRedirect(page);
}
else {
RequestDispatcher dispatcher = request.getRequestDispatcher(page);
dispatcher.forward(request, response);
}
}
}
</head>
<body>
<table>
<thead>
<tr>
<td><input type="checkbox"></td>
<td>상품이미지</td>
<td>상품명</td>
<td>단가</td>
<td>수량</td>
<td>총 가격</td>
<td>등록 일자</td>
</tr>
</thead>
<tbody>
<c:forEach var="cart" items="${cartList}">
<tr>
<td><input type="checkbox" ></td>
<td>
<!-- cart-mapper 페이지를 보고 판단하고 작성하기!!! -->
<img width="200px" height="260px" src="images/${cart.imgDTO.attachedName}">
</td>
<!-- cart-mapper 페이지를 보고 판단하고 작성하기!!! -->
<td>${cart.itemDTO.itemName }</td>
<td>${cart.itemDTO.itemPrice }</td>
<td>${cart.putCnt }</td>
<td>${cart.totalPrice }</td>
<td>${cart.putDate }</td>
</tr>
</c:forEach>
</tbody>
</table>
<div class="btns" align="center">
<input type="button" value="구매하기" onclick="location.href='';">
<input type="button" value="뒤로가기" onclick="history.go(-1)">
</div>
</body>
</html>
--병합하기
MERGE INTO SHOP_CART
USING DUAL --암기
ON (ITEM_CODE = 'ITEM_005'
AND MEM_ID = 'abc')--두개가 모두 일치해야한다.
WHEN MATCHED THEN--조건검사가 일치한다면 실행될 쿼리
UPDATE --테이블명 같이 x
SET
PUT_CNT = PUT_CNT + 1 --기존에 들어온 값 + 새로 들어온 값
,TOTAL_PRICE = --수량 *단가
WHERE ITEM_CODE = ?
AND MEM_ID = ?
WHEN NOT MATCHED THEN--조건검사가 불일치 했을 때 실행될 쿼리
INSERT (
CART_CODE
,ITEM_CODE
,MEM_ID
,PUT_CNT
,TOTAL_PRICE
) VALUES (
(SELECT 'CART_'||LPAD(NVL(MAX(TO_NUMBER(SUBSTR(CART_CODE, 6))), 0) + 1, 3, 0) FROM SHOP_CART)
, ?
, ?
, ?
, ? * (SELECT ITEM_PRICE
FROM SHOP_ITEM
WHERE ITEM_CODE =?)
);
delete from shop_cart; -> 장바구니 테이블 내 데이터 삭제후 다시 실행해야함!
<!-- 장바구니 등록 -->
<!-- 서브쿼리사용해서 총 가격 값 구한다 -->
<!-- (수정)
장바구니에서 같은 상품끼리는 병합 -->
<insert id="insertCart">
MERGE INTO SHOP_CART
USING DUAL
ON (ITEM_CODE = #{itemCode} AND MEM_ID = #{memId})
WHEN MATCHED THEN
UPDATE
SET
PUT_CNT = PUT_CNT + #{putCnt}
,TOTAL_PRICE = (PUT_CNT + #{putCnt}) * (SELECT ITEM_PRICE FROM SHOP_ITEM WHERE ITEM_CODE = #{itemCode})
WHERE ITEM_CODE = #{itemCode}
AND MEM_ID = #{memId}
WHEN NOT MATCHED THEN
INSERT (
CART_CODE
,ITEM_CODE
,MEM_ID
,PUT_CNT
,TOTAL_PRICE
) VALUES (
(SELECT 'CART_'||LPAD(NVL(MAX(TO_NUMBER(SUBSTR(CART_CODE, 6))), 0) + 1, 3, 0) FROM SHOP_CART)
, #{itemCode}
, #{memId}
, #{putCnt}
, #{putCnt} * (SELECT ITEM_PRICE
FROM SHOP_ITEM
WHERE ITEM_CODE = #{itemCode})
)
</insert>
void insertCart(CartDTO cartDTO);
실습내용
- 총 가격을 처음부터 ITEM_PRICE 를 VARCHAR2로 만들어서 99,999 있지만,
우리는 int 정수값으로 선언했기때문에 원래 만든 장바구니목록 페이지에서 구현하도록 해본다.
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<td><fmt:formatNumber pattern="₩#,##0" value="${cart.itemDTO.itemPrice }"/> </td>
<td><fmt:formatNumber pattern="₩#,#00" value="${cart.totalPrice }"/> </td>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri= "http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
table{
width: 80%;
border: 1px solid black;
border-collapse: collapse;
background-color: #FFFDE3;
margin: 0 auto;
text-align: center;
}
tr,td{
border: 1px solid black;
border-collapse: collapse;
background-color: #FFD39A;
margin: 0 auto;
text-align: center;
}
table > tr:first-child {
background-color: #FFFDE3;
}
.btns{
width: 100%;
margin-top: 20px;
}
input([type="button"]){
height: 40px;
width: 150px;
font-size: 25px;
background-color: #B1D7B4;
border-color: #B1D7B4;
color: #224B0C;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<td><input type="checkbox"></td>
<td>상품이미지</td>
<td>상품명</td>
<td>단가</td>
<td>수량</td>
<td>총 가격</td>
<td>등록 일자</td>
</tr>
</thead>
<tbody>
<c:forEach var="cart" items="${cartList}">
<tr>
<td><input type="checkbox" ></td>
<td>
<!-- cart-mapper 페이지를 보고 판단하고 작성하기!!! -->
<img width="100px" height="130px" src="images/${cart.imgDTO.attachedName}">
</td>
<!-- cart-mapper 페이지를 보고 판단하고 작성하기!!! -->
<td>${cart.itemDTO.itemName }</td>
<!-- 단가 쉼표 표시로 나오도록 만들기 -->
<td><fmt:formatNumber pattern="₩#,##0" value="${cart.itemDTO.itemPrice }"/> </td>
<td>${cart.putCnt }</td>
<!-- 총가격 쉼표 표시로 나오도록 만들기 -->
<td><fmt:formatNumber pattern="₩#,#00" value="${cart.totalPrice }"/> </td>
<td>${cart.putDate }</td>
</tr>
</c:forEach>
</tbody>
</table>
<div class="btns" align="center">
<input type="button" value="구매하기" onclick="location.href='';">
<input type="button" value="뒤로가기" onclick="history.go(-1)">
</div>
</body>
</html>
실습내용
- 메뉴판 체크박스를 체크할 때, 자동으로 전체 체크하도록 체크박스 기능 구현하기.
- 체크박스 태그 선택하기
- 자바스크립트 cart_list.js 파일 생성
- 기본적인 상태가 체크 상태이도록 checked 속성의 값을 'checked'으로 부여
- 먼저 제목줄 체크박스는 cart_list.jsp 에서 id 값 부여하기
<td><input type="checkbox" id="allChk" checked></td>
- 제목줄 아래 체크박스는 cart_list.jsp 에서 class 속성 값 부여하기
<td><input type="checkbox" class="chk" checked></td>
-> 똑같은 값이 반복되면 if문안의 값들은 id 속성 안되고 class 속성으로 만들어야한다.- 그리고 cart_list.js가서 id값,class값으로 태그 선택하기.
const allChk = document.querySelector('#allChk');
//제목 행의 체크박스의 체크여부를 확인
const allChk = document.querySelector('#allChk');
//제목 줄의 체크박스가 클릭되면..
allChk.addEventListener('click',function(){
//alert(allChk.checked);
//allChk.id; //allChk
//allChk.type;//checkbox
const isChecked = allChk.checked;//체크된 제목줄 체크박스를 isChecked라고 한다.
//클래스가 chk 인 태그들을 모두 데리고 온다.
// 장바구니의 모든 체크박스를 체크한다.
const chk = document.querySelectorAll('.chk');
//제목 줄의 체크박스가 체크 됐다면..
if(isChecked){
//chk.checked = true;
//자바스크립트는 for문사용가능하나 자료형이 없어서 int 사용은 안한다
for(i = 0; i<chk.length; i++){
chk[i].checked = true;//체크된 클래스가 chk의 값은 true로 준다.
}
//자바스크립트의 for-each문: of를 사용한다!
//for(const e of chk){
// e.checked = true;
//}
}
else{
for(i = 0; i<chk.length; i++){
chk[i].checked = false;//체크된 클래스가 chk의 값은 true로 준다.
}
}
});
실습내용
- 장바구니 목록페이지에서 제목줄 아래에 있는 체크박스가 전부 체크가 되면 제목 체크박스가 체크되도록 기능 구현하기
- hint
-> 아래에 있는 전체 체크박스의 수
-> 아래에 있는 전체 체크박스 중 체크된 수
//제목줄 아래 체크박스칸들이 전부! 체크가 된다면..
//제목줄 아래 체크박스칸들이 전부! 가져온다.
const chk = document.querySelectorAll('.chk');
for(const e of chk){
//원래라면..
//매개변수 e
//e.addEventListener('click',function(e){});
//위의 이벤트문을 조금 변경한다면..
e.addEventListener('click',e=>{
const cnt = chk.length; //제목줄 밑의 전체 체크박스의 갯수는 cnt
const checkedCnt = document.querySelectorAll('.chk:checked').length; //클래스가 chk 인 것들 중에서 체크된것만 들고오겠다.그것의 갯수.
if(cnt == checkedCnt){
document.querySelector('#allChk').checked = true;
}
else{
document.querySelector('#allChk').checked = false;
}
});
}