🌈 쇼핑몰 실습: 로그인 후 상품 추가·수정·삭제, 장바구니 구현
1. 세션(Session)이란?
- 세션은 서버가 클라이언트를 구분하기 위한 정보 저장 공간
- 로그인한 사용자 정보를 유지하거나, 특정 동작 후 돌아갈 목적지(destination)를 저장할 때 사용
- HttpSession 객체를 통해 관리 (setAttribute, getAttribute, invalidate 등)
사용한 sql문
-------------------------------------------------------------------------------------
-- 회원 테이블
-------------------------------------------------------------------------------------
DROP TABLE members CASCADE CONSTRAINTS;
create table members(
id varchar2(10) primary key,
name varchar2(30),
password varchar2(30),
gender varchar2(10),
hobby varchar2(70),
address varchar2(30),
mpoint number default 0
) ;
insert into members(id,name,password,gender,hobby,address)
values('kim','김철수','1234','남자','게임','서울');
insert into members(id,name,password,gender,hobby,address)
values('hong','홍길동','1234','남자','공부','부산');
insert into members(id,name,password,gender,hobby,address)
values('park','권지현','1234','여자','마라톤,공부','제주');
commit ;
col id for a6
col password for a8
col name for a8
col gender for a6
col hobby for a15
col address for a10
col job for a6
select * from members;
-------------------------------------------------------------------------------------
-- 상품 테이블
-------------------------------------------------------------------------------------
drop sequence seqprod ;
create sequence seqprod start with 1 increment by 1 nocache ;
DROP TABLE products CASCADE CONSTRAINTS;
-- name : 상품명, company : 제조 회사, image : 상품 이미지
-- stock : 재고 수량, point : 적립 포인트, inputdate : 입고 일자, category : 카테고리
create table products(
num int primary key,
name varchar2(50) not null,
company varchar2(50),
image varchar2(30),
stock int default 0,
price int default 0,
category varchar2(12),
contents varchar2(300),
point int default 0,
inputdate date default sysdate
);
-------------------------------------------------------------------------------------
insert into products(num, name, company, image, stock, price, category, contents, point, inputdate)
values(seqprod.nextval, '소보루', '샤니', 'orange.jpg', 100, 1000, 'bread', '맛있어요', 10, sysdate );
insert into products(num, name, company, image, stock, price, category, contents, point, inputdate)
values(seqprod.nextval, '크림빵', '샤넬', 'blueberry.jpg', 50, 2000, 'bread', '맛있어요', 20, sysdate );
insert into products(num, name, company, image, stock, price, category, contents, point, inputdate)
values(seqprod.nextval, '콜라', '코카', 'melon.jpg', 30, 3000, 'beverage', '탁쏩니다', 30, sysdate );
insert into products(num, name, company, image, stock, price, category, contents, point, inputdate)
values(seqprod.nextval, '사이다', '칠성', 'kiui.jpg', 40, 4000, 'beverage', '탁쏩니다', 40, sysdate );
insert into products(num, name, company, image, stock, price, category, contents, point, inputdate)
values(seqprod.nextval, '환타', '코카', 'melon.jpg', 50, 5000, 'beverage', '탁쏩니다', 50, sysdate );
insert into products(num, name, company, image, stock, price, category, contents, point, inputdate)
values(seqprod.nextval, '치킨', '네네', 'pine.jpg', 50, 5000, 'chicken', '맛없어요', 60, sysdate);
commit ;
col name for a6
col company for a6
col category for a8
col stock for 999
col num for 99
col point for 99
col price for 9999
col contents for a10
col image for a14
select * from products;
-------------------------------------------------------------------------------------
-- 주문 (매출) 테이블
-------------------------------------------------------------------------------------
drop sequence seqoid ;
create sequence seqoid start with 1 increment by 1 nocache ;
DROP TABLE orders CASCADE CONSTRAINTS;
-- oid : 주문(송장) 번호, mid : 회원 번호, orderdate : 주문 일자
create table orders(
oid number primary key,
mid varchar2(10) references members(id) on delete set null,
orderdate date default sysdate
);
select * from orders;
------------------------------------------------------------------------------------------------------
-- orderdetails : 주문 상세 테이블
-------------------------------------------------------------------------------------
drop sequence seqodid;
create sequence seqodid start with 1 increment by 1 nocache ;
-- oid : 주문번호, pnum : 상품 번호, qty : 주문 수량
drop table orderdetails purge ;
create table orderdetails(
odid number primary key,
oid number references orders(oid) on delete cascade,
pnum number references products(num) on delete set null,
qty number
);
select * from orderdetails;

화면 흐름
로그인X ➡️ 수정OR삭제OR 추가(삽입)시 ➡️ 로그인창 ➡️ 로그인 성공 ➡️ 수정OR삭제OR 추가폼



2. 로그인 로직 (MemberController)
화면 이미지 🔽

// home.html 로그인폼 이동
@GetMapping(value = "/login.mb")
public String login(){
return "member/memberLoginForm";
}
// memberLoginForm.html에서 submit
@PostMapping(value ="/login.mb")
public String loginProc(MemberDto mDto, HttpSession session, HttpServletResponse response) throws IOException {
// 1. 입력받은 아이디로 DB 조회
MemberDto member = memberMapper.findById(mDto.getId());
// 2. 회원이 없으면
if(member == null){
return "member/memberLoginForm"; // 로그인 폼 다시 이동
}
// 3. 회원이 있으면 비밀번호 확인
if(member.getPassword().equals(mDto.getPassword())){
// ✅ 로그인 성공 → 세션에 로그인 정보 저장
session.setAttribute("loginInfo", member);
// ✅ 이전에 가려던 페이지(destination)가 있으면 거기로 이동
String destination = (String)session.getAttribute("destination");
if(destination == null){
return "home";
} else {
return destination;
}
}else{
return "member/memberLoginForm"; // 로그인 실패
}
}
입력받은 id로 DB조회
| MemberDto member = memberMapper.findById(mDto.getId()); |
| 존재하지 않는 id ➡️ 로그인 화면 다시 이동 |
| 존재하는 id ➡️ 비밀번호 확인 |
로그인화면에서 아이디 비밀번호 입력 후 submit
| ⭕ 로그인 성공 |
| session.setAttribute("loginInfo", member); → 로그인 사용자 정보 저장 |
| destination 세션값 확인 후 원래 가려던 페이지로 리다이렉트 |
| ❌로그인 실패 |
| 로그인 화면 다시 띄우기 |
3. 로그아웃 (MemberController)
화면 이미지 🔽

home.html 에서 로그아웃 버튼 클릭시 로그아웃
// 로그아웃
@GetMapping(value = "/logout.mb")
public String logout(HttpSession session){
session.invalidate(); // 세션 강제종료
return "redirect:/";
}
➡️invalidate() : 로그인 상태 해제, 세션 초기화
4. 상품 관리 시 세션 체크 (ProductsController)
화면 이미지 🔽

추가하기 버튼 클릭시 삽입폼 이동
(1) 삽입(insert) -> 삽입 폼으로 이동
@GetMapping("/pinsert.prd")
public String insertForm(HttpSession session, @ModelAttribute("pDto") ProductsDto pDto){
if(session.getAttribute("loginInfo") == null){
// 로그인 안 되어 있으면 → 로그인 페이지로 이동
session.setAttribute("destination", "redirect:/pinsert.prd");
return "redirect:/login.mb";
}
return "products/productInsert"; // 로그인 되어 있으면 삽입폼으로
}
(2) 수정(update) -> 수정 폼으로 이동
// 수정폼으로 이동 (UpdateForm 이동)
@GetMapping(value = "/pupdate.prd")
public String updateForm(
HttpSession session,
@RequestParam("num") int num, Model model,
@RequestParam(value = "whatColumn", required = false) String whatColumn,
@RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "page",defaultValue = "1") int page
){
if(session.getAttribute("loginInfo")==null){
String encodeKeyword = keyword != null ? URLEncoder.encode(keyword, StandardCharsets.UTF_8) : "";
session.setAttribute("destination", "redirect:/pupdate.prd?num=" + num
+ "&page=" + page
+ "&whatColumn=" + whatColumn
+ "&keyword=" + encodeKeyword);
return "redirect:/login.mb";
}else{
ProductsDto pDto = productsMapper.findByNum(num);
model.addAttribute("keyword", keyword);
model.addAttribute("whatColumn", whatColumn);
model.addAttribute("page", page);
model.addAttribute("pDto", pDto);
return "products/productUpdate";
}
수정(update) -> 수정 처리
// 수정처리 (Update)
@PostMapping(value = "/pupdateProc.prd")
public String updateProc(@RequestParam("num") int num, HttpSession session,
@ModelAttribute("pDto") @Valid ProductsDto pDto,BindingResult br, Model model,
@RequestParam(value = "whatColumn", required = false) String whatColumn,
@RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "page",defaultValue = "1") int page
) {
if(session.getAttribute("loginInfo") == null){
String encodeKeyword = keyword != null ? URLEncoder.encode(keyword, StandardCharsets.UTF_8) : "";
session.setAttribute("destination", "redirect:/pupdate.prd?num=" + num
+ "&page=" + page
+ "&whatColumn=" + whatColumn
+ "&keyword=" + encodeKeyword);
return "redirect:/login.mb";
}else{
model.addAttribute("keyword", keyword);
model.addAttribute("whatColumn", whatColumn);
model.addAttribute("page", page);
model.addAttribute("pDto", pDto);
// 유효성 검정
if(pDto.getFile() == null || pDto.getFile().isEmpty()) {
br.rejectValue("file", "file.empty", "파일을 선택해주세요.");
}
if(br.hasErrors()) {
return "products/productUpdate";
}
// 폴더 업로드
MultipartFile file = pDto.getFile();
String original = file.getOriginalFilename(); // 원본 파일명
Path target = Paths.get(uploadDir,original); // 저장할 경로
try {
file.transferTo(target.toFile()); // 실제 파일 저장
} catch (IOException e) {
throw new RuntimeException(e); // 예외 발생 시 런타임 에러
}
// DB에 저장할 파일명 세팅
pDto.setImage(original);
String resultPage = "";
if (br.hasErrors()) {
resultPage = "products/productUpdate";
} else {
productsMapper.updateProduct(pDto);
String encodeKeyword = keyword != null ? URLEncoder.encode(keyword, StandardCharsets.UTF_8) : "";
resultPage = "redirect:/plist.prd?page=" + page + "&whatColumn=" + whatColumn + "&keyword=" + encodeKeyword;
}
return resultPage;
}
}
(3) 삭제(delete) -> 삭제 요청시
@GetMapping(value="/pdelete.prd")
public String deleteProc(
HttpSession session,
@RequestParam("num") int num, Model model,
@RequestParam(value = "whatColumn", required = false) String whatColumn,
@RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "page",defaultValue = "1") int page
) {
if (session.getAttribute("loginInfo") == null) {
String encodeKeyword = keyword != null ? URLEncoder.encode(keyword, StandardCharsets.UTF_8) : "";
session.setAttribute("destination", "redirect:/pdelete.prd?num="+num
+ "&page=" + page
+ "&whatColumn=" + whatColumn
+ "&keyword=" + encodeKeyword);
return "redirect:/login.mb";
} else {
model.addAttribute("keyword", keyword);
model.addAttribute("whatColumn", whatColumn);
model.addAttribute("page", page);
// ✅ 1. 삭제 전, 해당 상품의 이미지 파일명 조회 (이미지 파일 삭제)
ProductsDto pDto = productsMapper.findByNum(num);
if (pDto != null && pDto.getImage() != null) {
Path filePath = Paths.get(uploadDir, pDto.getImage());
File file = filePath.toFile(); // Path → File 객체 변환
file.delete(); // 2) 파일삭제 방법2
System.out.println("이미지 삭제 성공 :" + file);
}
// ✅ 2. DB 레코드 삭제
productsMapper.deleteProduct(num);
// ✅ 3. 페이징 처리
int limit = 5;
int offset = (page - 1) * limit;
Map<String, Object> params = new HashMap<String, Object>();
params.put("whatColumn", whatColumn);
params.put("keyword", keyword);
params.put("offset", offset);
params.put("limit", limit);
int totalCount = productsMapper.getCount(params);
if (totalCount % limit == 0) {
page = page - 1;
}
String encodeKeyword = keyword != null ? URLEncoder.encode(keyword, StandardCharsets.UTF_8) : "";
return "redirect:/plist.prd?page=" + page + "&whatColumn=" + whatColumn + "&keyword=" + encodeKeyword;
}
}
| 1. 로그인시 session.setAttribute("loginInfo", member); 👉 로그인에 성공하면 loginInfo라는 이름으로 회원정보(MemberDto)를 세션에 저장. |
| 2. 로그인 확인 : 세션에서 loginInfo를 꺼내와서(null인지 여부 확인) → 로그인 안 했는지 여부 판별. if(session.getAttribute("loginInfo") == null) { ... } |
| 3. 미로그인 → 로그인 페이지로 강제 이동 return "redirect:/login.mb"; |
| 4. 로그인 되어있으면 원래 작업 진행 |
5. 흐름 요약 (Session + Destination 활용)
✅ 로그인 X 상태
- 상품 삽입 / 수정 / 삭제 시도
- → 로그인 창 이동 (destination 에 원래 주소 저장)
- 로그인 성공
- → destination 값 확인 → 원래 시도한 페이지로 이동
✅ 로그인 O 상태
- 바로 삽입 / 수정 / 삭제 가능
6. 화면 흐름 (간단 다이어그램)
[로그인 X]
↓ (삽입/수정/삭제 버튼 클릭)
[로그인 페이지] ← destination 저장
↓ (로그인 성공)
[원래 목적지 폼]
[로그인 O]
↓
[바로 삽입/수정/삭제 폼]
7. 정리
- 세션(HttpSession)은 로그인 유지 + 권한 제어 + 이전 페이지 기억 에 활용된다.
- loginInfo : 로그인 사용자 정보 저장
- destination : 로그인 후 되돌아갈 주소 저장
- invalidate() : 로그아웃 시 세션 삭제
🌈8. 장바구니 구현 (MallController / mallList.html)
상품 상세에서 주문 버튼 주문버튼 클릭시 장바구니 이동
productContent.prd ➡️ mall.list 이동


(1) MyCartDto
package com.example.Ex02.dto;
import java.util.HashMap;
import java.util.Map;
public class MyCartList {
private Map<Integer, Integer> orderlists = null;
public MyCartList(){
orderlists = new HashMap<Integer, Integer>(); // key, value
// 3번 상품, 2개 주문
// 1번 상품, 5개 주문
}
// 장바구니 있는 상품을 더 추가할 경우
public void addOrder(int pnum, int oqty){
// orderlists : Map<Integer, Integer>
// key = 상품번호(pnum), value = 주문수량(qty)
if(orderlists.containsKey(pnum)){ // ✅ 이미 장바구니에 같은 상품이 있는 경우
Integer qty = orderlists.put(pnum, oqty);
int addQty = qty + oqty;
orderlists.put(pnum,addQty); // 기존 수량 + 새 수량으로 덮어쓰기
}else{// ✅새상품이면
orderlists.put(pnum,oqty); // 그대로 추가
}
}
public Map<Integer,Integer> getAllOrderlists(){
return orderlists;
}
}
(2) mallController
1. 장바구니 구현 컨트롤러에 로그인 세션 가져오기 (로그인 여부확인)
2. 장바구니 세션 생성
// productContent.prd => 주문버튼 클릭시 장바구니 이동
@PostMapping(value = "/add.mall")
public String add(ProductsDto product, HttpSession session,
@RequestParam(value = "whatColumn", required = false) String whatColumn,
@RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "page",defaultValue = "1") int page
){
System.out.println("product.getNum()" + product.getNum());
System.out.println("product.getOrerqty()" + product.getOrderqty());
// memberController에서 설정한 loginInfo를 get으로 불러와서 사용
// 1. 로그인 여부 확인 (세션에 "loginInfo"가 없으면 로그인 안된 상태)
if(session.getAttribute("loginInfo") == null){
String encodeKeyword = keyword != null ? URLEncoder.encode(keyword, StandardCharsets.UTF_8) : "";
session.setAttribute("destination", "redirect:/pcontent.prd?" +
"num="+product.getNum()
+"&page="+page
+"&whatColumn="+whatColumn
+"&keyword=" +encodeKeyword);
return "redirect:/login.mb";
}else{
// 2. 로그인 된 경우 → 장바구니 처리
// 장바구니 세션 설정 : mycart
MyCartList mycart = (MyCartList) session.getAttribute("mycart");
System.out.println("mycart1 : " + mycart);
if(mycart == null){ // 3. 장바구니가 없다면 == > 장바구니 생성
mycart = new MyCartList(); // "장바구니 객체" 생성
}
System.out.println("mycart2 : " + mycart);
// 4. 장바구니에 상품 추가
mycart.addOrder(product.getNum(), product.getOrderqty());
// 5. 장바구니를 계속 끌고다닐수 있도록 세션 설정
session.setAttribute("mycart", mycart);
return "redirect:/list.mall";
}
}
(3) mallList.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3 style="text-align:center;">mall/mallList</h3>
<div th:insert ="~{fragment :: header}"></div>
<table border="1" width="400" style="text-align:center; border-collapse:collapse;">
<!-- 주문자 정보 -->
<tr>
<th colspan="5" class="order-info">
주문자 :
<span th:text="${session.loginInfo.name}"></span>
(<span th:text="${session.loginInfo.id}"></span>)
</th>
</tr>
<!-- 헤더 -->
<tr>
<th>상품번호</th>
<th>상품명</th>
<th>주문수량</th>
<th>단가</th>
<th>금액</th>
</tr>
<!-- 상품 목록 반복 -->
<tr th:each="product : ${shopLists}">
<td th:text="${product.pnum}"></td>
<td th:text="${product.pname}"></td>
<td th:text="${product.qty}"></td>
<td th:text="${#numbers.formatDecimal(product.price,0,'COMMA',0,'POINT')}"></td>
<td th:text="${#numbers.formatDecimal(product.amount,0,'COMMA',0,'POINT')}"></td>
</tr>
<!-- 총 합계 -->
<tr class="total-row">
<td colspan="2">총 합계</td>
<td colspan="3"
th:text="${#numbers.formatDecimal(totalAmount, 0, 'COMMA', 0, 'POINT')}"></td>
</tr>
</table>
<!-- 액션 버튼 -->
<div class="actions">
<a th:href="@{/calculate.mall}">결제하기</a> |
<a th:href="@{/plist.prd}">추가 주문</a>
</div>
</body>
</html>
🌈9. 주문내역 구현 (MallController)
💳 결제 완료(calculate.mall) 시
- 이미 장바구니의 데이터를 기반으로
orders (주문 테이블)
orderdetails (주문 상세 테이블)
에 영구 저장(DB insert) 됨
→ 즉, 장바구니의 정보는 “주문으로 승격됨”. - 결제가 끝났는데 장바구니를 그대로 두면,
- 사용자가 “결제하기” 버튼을 다시 누르면 중복 주문 발생 위험 ⚠️
- 결제 완료 후에도 장바구니에 남아 있으면 UX 혼란
(“이거 아직 결제 안 된 건가?”처럼 보임)
- 그래서 결제 완료 후엔 즉시:
session.removeAttribute("mycart");
→ 세션에서 mycart 객체를 삭제하여 장바구니를 완전히 비움.
→ 즉, 새 쇼핑을 시작할 수 있는 “초기 상태”로 되돌림

orderMapper 전체코드
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--orders.xml-->
<mapper namespace="com.example.Ex02.mapper.OrderMapper">
<insert id="insertOrder" parameterType="com.example.Ex02.dto.OrderDto">
insert into orders (oid, mid, orderdate)
values (seqoid.nextval, #{mid}, sysdate)
</insert>
<!--가장 큰 oid값 -->
<select id="getMaxOid" resultType="int">
select max(oid)
from orders
</select>
<!--주문자 주문목록 찾기-->
<select id="orderMall">
select * from orders
where mid = #{id}
order by oid desc
</select>
<!--주문 상세보기-->
<select id="showDetail">
select num as pnum, name as pname, qty, price, qty*price as amount
from (orders o inner join orderdetails od
on o.oid = od.oid) inner join products
on pnum = num and o.oid = #{oid}
</select>
</mapper>
(1) MallController
orderMapper.insertOrder() : 주문 기분정보 DB저장
orderMapper.getMaxOid() : 방금 넣은 주문의 PK가져오기
orderDetailsMapper.insertOrderDetails() : 상세보기dto에 값넣기
productsMapper.updateStock(pDto) : 주문시 장품 재고 차감
memberMapper.addPoint(member) : 주문시 포인트 적립
member은 사용자로그인 정보 (세션)으로 가져옴
orderDatailMapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--orderdetails.xml-->
<mapper namespace="com.example.Ex02.mapper.OrderDetailsMapper">
<insert id="insertOrderDetails">
insert into orderdetails
values(seqodid.nextval, #{oid}, #{pnum}, #{qty})
</insert>
</mapper>
(장바구니 → 주문 테이블 → 주문상세 테이블 → 포인트 적립 → 장바구니 비우기)
// 💳 주문내역 처리 (mallList.html에서 "결제하기" 클릭 시 실행)
@GetMapping(value = "/calculate.mall")
public String calculate(HttpSession session, Model model) {
// ✅ 1️⃣ 세션에서 장바구니 정보 가져오기
// (장바구니는 MyCartList 객체로 세션에 저장되어 있음)
MyCartList mycart = (MyCartList) session.getAttribute("mycart");
// 장바구니가 비어있지 않은 경우에만 주문 처리
if (mycart != null) {
// ✅ 2️⃣ 장바구니의 전체 상품목록 가져오기
// 예시: {4=3, 6=2} → 상품번호 4는 3개, 상품번호 6은 2개
Map<Integer, Integer> maplists = mycart.getAllOrderlists();
// ✅ 3️⃣ 로그인한 사용자 정보 가져오기 (주문자 ID 저장용)
MemberDto member = (MemberDto) session.getAttribute("loginInfo");
// ✅ 4️⃣ 주문 기본정보 저장 (orders 테이블)
// 주문자 ID(mid)만 먼저 넣고, 나머지는 DB에서 자동 처리 (oid는 시퀀스로)
OrderDto orderDto = new OrderDto();
orderDto.setMid(member.getId()); // ex) "kim"
orderMapper.insertOrder(orderDto); // → orders 테이블에 삽입
// ✅ 5️⃣ 방금 저장한 주문의 고유번호(oid) 가져오기
// 최신 주문의 PK(oid)를 구해서 주문상세(orderdetails)에 연결하기 위함
Set<Integer> keylist = maplists.keySet(); // ex) [4, 6, 10]
int maxOid = orderMapper.getMaxOid(); // ex) 23 (이번 주문번호)
System.out.println("maxOid: " + maxOid);
// ✅ 6️⃣ 장바구니의 모든 상품을 반복하면서 주문상세(orderdetails)에 저장
for (Integer pnum : keylist) {
OrderDetailDto odDto = new OrderDetailDto();
// 해당 상품의 수량 가져오기
int qty = maplists.get(pnum);
System.out.println("qty: " + qty);
// 주문상세 데이터 설정
odDto.setOid(maxOid); // 주문번호(FK)
odDto.setPnum(pnum); // 상품번호
odDto.setQty(qty); // 수량
// DB에 주문상세 레코드 추가
orderDetailsMapper.insertOrderDetails(odDto);
// ✅ 7️⃣ 상품 재고 차감 (상품테이블 업데이트)
ProductsDto pDto = new ProductsDto();
pDto.setNum(pnum);
pDto.setStock(qty);
productsMapper.updateStock(pDto); // → stock = stock - qty
} // for
// ✅ 8️⃣ 주문 완료 시 포인트 적립 (예: 100점)
int point = 100;
member.setId(member.getId());
member.setMpoint(point);
memberMapper.addPoint(member);
} // if(mycart != null)
// ✅ 9️⃣ 결제 완료 후 장바구니 세션 비우기
// (중복 결제 방지 및 새로운 쇼핑을 위한 초기화)
session.removeAttribute("mycart");
// ✅ 🔟 결제 완료 후 상품 리스트 페이지로 이동
return "redirect:/plist.prd";
}
🌈10. 나의 주문내역보기 구현 (MallController)




(1) 나의 주문내역 보기
orderMapper.orderMall() : mapper에서 사용자 ID로 주문목록 조회
// 나의 주문내역 보기
@GetMapping(value = "/order.mall")
public String order(HttpSession session, Model model){
// ✅ 1️⃣ 로그인 정보 확인
// 세션에 저장된 로그인 사용자 정보(loginInfo) 가져오기
MemberDto loginInfo = (MemberDto)session.getAttribute("loginInfo");
// ✅ 2️⃣ 로그인하지 않은 경우 → 로그인 페이지로 이동
if(loginInfo == null){
session.setAttribute("destination", "redirect:/order.mall");
return "redirect:/login.mb";
}else{
// ✅ 3️⃣ 로그인한 경우 → 해당 사용자의 주문 내역 조회
// orderMapper.orderMall() : mapper에서 사용자 ID로 주문 목록 조회
List<OrderDto>lists = orderMapper.orderMall(loginInfo);
model.addAttribute("lists", lists);
}
return "mall/shopList";
}
(2) 나의 주문내역 상세보기
orderMapper.showDeatail()
// 🧾 나의 주문내역 상세보기
@GetMapping(value = "/detailview.mall")
public String detailview(@RequestParam("oid") int oid, HttpSession session, Model model) {
// ✅ 1️⃣ 로그인 여부 확인
// 세션에서 로그인한 사용자 정보(loginInfo) 가져오기
MemberDto loginInfo = (MemberDto) session.getAttribute("loginInfo");
// ✅ 2️⃣ 로그인하지 않은 경우 → 로그인 페이지로 이동
if (loginInfo == null) {
// 로그인 성공 후 돌아올 페이지를 저장
session.setAttribute("destination", "redirect/plist.prd");
// 로그인 페이지로 리다이렉트
return "redirect:/login.mb";
}
// ✅ 3️⃣ 로그인한 경우 → 주문 상세내역 조회
else {
// 주문 번호(oid)를 모델에 담기 (View에서 사용 가능)
model.addAttribute("oid", oid);
// ✅ 4️⃣ 매퍼 호출: 주문상세(orderdetails)와 상품(products) 테이블을 조인하여 상세정보 조회
List<ShoppingInfo> lists = orderMapper.showDetail(oid);
System.out.println("lists.size() : " + lists.size());
model.addAttribute("lists", lists);
// 주문상세 결과 페이지(shopResult.html)로 이동
return "mall/shopResult";
}
/*
📌 Mapper 설명
orderdetails 테이블의 pnum(상품번호)과
products 테이블의 num(상품번호)을 JOIN하여
주문 상세 정보(상품명, 수량, 가격 등)를 함께 조회.
*/
}
“로그인한 사용자가 특정 주문번호(oid)의 상세내역을 조회하는 메서드로,
주문상세(orderdetails)와 상품정보(products)를 조인하여
하나의 리스트로 View에 전달한다.”
'기초 및 언어 > ▶ Spring' 카테고리의 다른 글
| 15. Spring Boot JPA + 쿼리 어노테이션(jpql) (0) | 2025.10.01 |
|---|---|
| 14. Spring Number, 단위마다 , 붙이기 (0) | 2025.10.01 |
| 12. Spring 파일 관리 주요 기능/메서드 정리 (0) | 2025.09.30 |
| 11. Spring 쇼핑몰_파일첨부와_이미지출력 (0) | 2025.09.30 |
| 10. Spring Boot_fetch(중복 검사) (0) | 2025.09.28 |