20221019_wed
어제 내용 정리
선택구매 DB insert시키기
- 먼저, BUY-MAPPER에서 쿼리문작성을 해야한다.
: sop_buy 테이블과 shop_buy_detail 테이블에도 동시에 구매정보 데이터가 들어가야한다.
둘 다 공통적으로 buy_code가 있다. 그래서 insert하기전에 다음에 들어갈 buy_code값을 조회해서 두 테이블에 넣어줘야하는 것을 알아야한다.- mapper에서 buy테이블 insert쿼리문과 buy_deatil테이블 insert쿼리문을 작성한 뒤, 다음buyCode를 조회하는 nextCode쿼리문도 작성한다.
- service,serviceImpl까지 모두 작성 후, controller에서 이동경로 만들어준다.
: controller에서 이전에 만들어놓은 쿼리문들을 가져와 사용한다.- cartCode 컬럼을 구매할 상품목록조회 쿼리문에 추가해서 조회해준다.
<?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">
<!--해당 파일에 모든 쿼리문을 작성 -->
<mapper namespace="buyMapper">
<resultMap type="Kh.study.shop.buy.vo.BuyVO" id="buy">
<id column="BUY_CODE" property="buyCode"/>
<result column="MEMBER_ID" property="memberId"/>
<result column="BUY_DATE" property="buyDate"/>
<result column="TOTAL_PRICE" property="totalPrice"/>
<association property="cartVO" resultMap="cart"/>
</resultMap>
<resultMap type="Kh.study.shop.buy.vo.BuyDetailVO" id="buyDetail">
<id column="BUY_DETAIL_CODE" property="buyDetailCode"/>
<result column="ITEM_CODE" property="itemCode"/>
<result column="BUY_CODE" property="buyCode"/>
<result column="BUY_AMOUNT" property="buy_amount"/>
</resultMap>
<!-- buy_infohtml 뿌려줄 구매'할' 장바구니목록조회 -->
<!-- 방법1) 서브쿼리 사용 -->
<!-- 장바구니에 들어있는 아이템코드와 똑같은것만 itemName 조회하겠다.-->
<!-- 장바구니테이블에서 조회된 아이템코드와 같은 것일때의 상품명을 조회하겠다! -->
<!-- 실제로 내장바구니에서 선택한 것들만 들고와야한다! 그럴땐 조건절에 cartCode를 가져와야한다!! -->
<!-- ->위에서처럼 그럴땐, IN연산자를 사용해야한다!!! -->
<select id="selecteBuyingList" resultMap="cartMapper.cart"><!-- 기존에 있던 cart매퍼를 사용한다. -->
SELECT ITEM_CODE
,(SELECT ITEM_NAME
FROM SHOP_ITEM
WHERE ITEM_CODE = c.ITEM_CODE) AS ITEM_NAME
,(SELECT ITEM_PRICE
FROM SHOP_ITEM
WHERE ITEM_CODE = c.ITEM_CODE) AS ITEM_PRICE
, CART_AMOUNT
,(SELECT ATTACHED_NAME
FROM ITEM_IMG
WHERE ITEM_CODE = c.ITEM_CODE
AND IS_MAIN ='Y') AS ATTACHED_NAME
, CART_CODE
FROM SHOP_CART C
WHERE CART_CODE IN
<foreach collection="cartCodeList" item="cartCode" separator="," open="(" close=")" >
#{cartCode}
</foreach>
</select>
<!-- 방법2) 조인사용 -->
<!-- <select id="">
SELECT SHOP_ITEM.ITEM_CODE,ATTACHED_NAME,ITEM_NAME,ITEM_PRICE,CART_AMOUNT
FROM ITEM_IMG,SHOP_ITEM,SHOP_CART
WHERE ITEM_IMG.ITEM_CODE = SHOP_ITEM.ITEM_CODE
AND IS_MAIN ='Y'
AND SHOP_ITEM.ITEM_CODE = SHOP_CART.ITEM_CODE 여기까지는 모든 장바구니 목록조회
AND cart_code in ('cart_001','cart_002')
</select> -->
<!-- 구매!!정보!! 등록 -->
<!-- totalPrice는 받아도 안받아도 된다. -->
<insert id="insertBuy">
INSERT INTO SHOP_BUY(
BUY_CODE
, MEMBER_ID
, TOTAL_PRICE
<!-- , ITEM_CODE -->
)VALUES(
#{buyCode}
, #{memberId}
, #{totalPrice}
<!-- ,(SELECT CART_AMOUNT
FROM SHOP_CART
WHERE CART_CODE = #{cartCode})
* (SELECT ITEM_PRICE
FROM SHOP_ITEM
WHERE ITEM_CODE = #{itemCode}) -->
)
</insert>
<!-- 구매코드 1씩 증가 -->
<!--resultType="String" 의 뜻은 디비에서 실제로 쿼리실행했을 때 나오는 결과(buy_001)를 자바로 가져올때는 문자열로 가져오겠다. -->
<!-- LPAD(): 1씩 증가시키는데 세자리로 만들면서 나머지왼쪽부터 공백은 0으로 채우겠다. -->
<select id="selectNextBuyCode" resultType="String">
SELECT 'BUY_'||LPAD(NVL(MAX(TO_NUMBER(SUBSTR(BUY_CODE, 5))), 0) + 1, 3, 0)
FROM SHOP_BUY
</select>
<!-- 구매 상세 정보 테이블에도 등록-->
<!-- 한번에 여러 상세 상품정보 데이터가 들어가야한다. 이는 여러이미지 등록했을때와 같다! 찾아보면된다! -->
<insert id="insertBuyDetail">
INSERT INTO SHOP_BUY_DETAIL(
BUY_DETAIL_CODE
,ITEM_CODE
,BUY_CODE
,BUY_AMOUNT
)
<foreach collection="buyDetailList" item="buyDetailVO" separator="UNION ALL" index="i"><!-- BuyVO에 있는 BuyDetailList 변수를 가져와서 그 하나를하나 buyDetailVO라고 한다.-->
SELECT #{buyCode}||'_'||LPAD(#{i}+1,2,0)
, #{buyDetailVO.itemCode}
, #{buyCode}<!--이 빈값들을 채우기위해 BuyVO를 가져온다. 그래서 이미 BuyVO에는 buyCode값이 존재하기때문에 이렇게 적을 수 있다. -->
, #{buyDetailVO.buyAmount}
FROM DUAL
</foreach>
</insert>
<!-- 구매를 위한 장바구니 정보 조회 -->
<!-- cart_code가 'cart_001','cart_002'..일 때 -->
<!-- 위의 데이터의 총 total_price 조회 -->
<select id="getCartInfoForBuy" resultMap="cartMapper.cart">
SELECT ITEM_CODE,CART_AMOUNT,TOTAL_PRICE
FROM SHOP_CART
WHERE CART_CODE IN (
<foreach collection="cartCodeList" item="cartCode" separator="," >
#{cartCode}
</foreach>
)
</select>
<!-- 장바구니 선택삭제 --><!-- cart-mapper에도 있음! 먼저 만들어놓음 혹시몰라 가져옴... -->
<!--cartCodeList 에는 CART_001,CART_002,CART_003...이렇게 들어있다-->
<!-- cartCode는 위에 리스트안에 있는 하나하나 를 말한다. cart_001 -->
<!-- cartCodeList를 데이터로 가져올 때는 사실 cartVO.getCartCodeList(); getter호출과 같다 -->
<delete id="deleteCarts">
DELETE SHOP_CART
WHERE CART_CODE IN
<foreach collection="cartCodeList" item="cartCode" separator="," open="(" close=")" >
#{cartCode}
</foreach>
</delete>
</mapper>
package Kh.study.shop.buy.service;
import java.util.List;
import Kh.study.shop.buy.vo.BuyVO;
import Kh.study.shop.cart.vo.CartVO;
public interface BuyService {
//구매할 목록조회
List<CartVO> selecteBuyingList(CartVO cartVO);
String selectNextBuyCode();
//구매등록
void insertBuy(BuyVO buyVO);
//구매를 위한 장바구니 정보 조회
List<CartVO> getCartInfoForBuy(CartVO cartVO);
}
package Kh.study.shop.buy.service;
import java.util.List;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import Kh.study.shop.buy.vo.BuyVO;
import Kh.study.shop.cart.vo.CartVO;
@Service("buyService")
public class BuyServiceImpl implements BuyService{
@Autowired
private SqlSessionTemplate sqlSession;
//구매등록(+ 구매상세정보 같이 트랜잭션 처리해야한다)
@Transactional(rollbackFor = Exception.class)//어떤 오류든 간에 뭐든지 롤백하겠다.
@Override
public void insertBuy(BuyVO buyVO) {
sqlSession.insert("buyMapper.insertBuy",buyVO);
sqlSession.insert("buyMapper.insertBuyDetail",buyVO);
}
@Override
public String selectNextBuyCode() {
return sqlSession.selectOne("buyMapper.selectNextBuyCode");
}
//구매할 장바구니목록조회
@Override
public List<CartVO> selecteBuyingList(CartVO cartVO) {
return sqlSession.selectList("buyMapper.selecteBuyingList",cartVO);
}
//구매위한 장바구니정보조회
@Override
public List<CartVO> getCartInfoForBuy(CartVO cartVO) {
return sqlSession.selectList("buyMapper.getCartInfoForBuy",cartVO);
}
}
package Kh.study.shop.buy.controller;
@Controller
@RequestMapping("/buy")
public class BuyController {
@Resource(name = "cartService")
private CartService cartService;
@Resource(name = "buyService")
private BuyService buyService;
@Resource(name = "memberService")
private MemberService memberService;
// 선택구매
@RequestMapping("/buyInfo")
public String buyInfo(Model model,String cartCodes,CartVO cartVO,Authentication authentication) {
String[] cartCodeArr = cartCodes.split(",");// 위처럼 넘어오는 cartCodes를 쉼표',' 로 분리한다. 그럼 문자열이 여러개나와서 배열로 받아야한다.
List<String> cartCodeList= Arrays.asList(cartCodeArr);
cartVO.setCartCodeList(cartCodeList);
model.addAttribute("buyingList",buyService.selecteBuyingList(cartVO));//구매할 목록조회
//중요! memberId값은 항상 String memberId가 아니라 Authentication authentication 로 가져와야한다!!!
User user = (User)authentication.getPrincipal();
model.addAttribute("memberVO",memberService.selectMemberInfo(user.getUsername()));//구매자정보조회
// 전체 총 가격 데이터 (리스트에서 뽑아서 누적합으로 데이터 던져주기)
int finalPrice = 0;
for(CartVO e : cartService.selectCartList(user.getUsername())) {
finalPrice = finalPrice + e.getTotalPrice();
}
model.addAttribute("finalPrice",finalPrice);
return "content/buy/buy_info";
}
// 구매등록
@PostMapping("/insertBuy")
public String buyCart(String[] cartCodes, BuyVO buyVO,CartVO cartVO,Authentication authentication) {
//totalPrice,itemCode(들),수량(들) -> 데이터를 가져와야한다.
// 하지만!! cartCode(들)만 들고오면 위에 데이터들도 따라오게할 수 있다!!!
// cart테이블에가면 아이템코드 수량, 토탈프라이스 모두 있기때문에 cartCode만 알면 연결되 나머지 데이터들을 들고올 수 있다.
// cartCode(들)을 들고오는 방법은?
System.out.println("!@!!!!!!!!!!!!!!!!!!!@@@@" + cartCodes);// 콘솔확인시, CART_004,CART_007 -> 자스를 사용하지않아도 이런 식으로 데이터를 들고온다.
// 매개변수에서부터 배열 자료형으로 받으면(String[] cartCodes), 굳이 위에처럼 ,쉼표로 문자열을 자를 필요가 없다.
//for문을 돌려 하나씩빼서 콘솔 출력한다.
for(String e : cartCodes) {
System.out.println("@@@@@@@@@@@@@@@@@@@ " + e);
}
// buy_code 데이터 들고오기 : insert되어야하는 buy_code 조회
String buyCode = buyService.selectNextBuyCode();
//totalPrice,itemCode(들),cartAmount(들) 데이터는 어떻게 들고오냐
//위에 알고있는 cartCode를 이용해서 위 데이터를 쿼리문을 통해 가져온다. -> buy-mapper에서 만들어주기.
// 우리가 들고온 cartCode들을 cartVO에 넣어줘야한다.
// 이미 cartVo에는 리스트형태로 cartCodeList가 있는데, 이를 배열의 형태로 바꾸어 넣어준다.
List<String> cartCodeList = Arrays.asList(cartCodes);
cartVO.setCartCodeList(cartCodeList);
List<CartVO> cartList = buyService.getCartInfoForBuy(cartVO);
List<BuyDetailVO> buyDetailList = new ArrayList<>(); //아래 데이터 넣기위해서 미리 통만들기(변수선언)
//반복해서 itemCode와 amount값,totalPrice값 모두 for문돌려서 하나씩 빼기
int totalPrice =0;
for(CartVO cart : cartList) {
totalPrice = totalPrice + cart.getTotalPrice();
//아래처럼 만들어준 것을 위에 buydetailList 통에 넣어준다.
BuyDetailVO vo = new BuyDetailVO();
vo.setItemCode(cart.getItemCode());
vo.setBuyAmount(cart.getCartAmount());
buyDetailList.add(vo);
}
//memberID 데이터가져오기
User user = (User)authentication.getPrincipal();
// 위에서 부터 가져온 모든 데이터들을 BuyVO에서 setter를 이용해 데이터 넣어주기
buyVO.setBuyCode(buyCode);
buyVO.setMemberId(user.getUsername());
buyVO.setTotalPrice(totalPrice);
buyVO.setBuyDetailList(buyDetailList);// buyDetailVO 에서 itemCode,cartAmount값 가져오기.
//실제 구매실행 쿼리문
buyService.insertBuy(buyVO);
return "content/buy/buy_list";
}
//구매 목록조회
/*
* @GetMapping("/buyList") public String buyList() { return
* "content/buy/buy_list"; }
*/
}
20221019 12:24:39.574 [http-nio-8081-exec-1] DEBUG j.sqltiming - com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
1483. SELECT 'BUY_'||LPAD(NVL(MAX(TO_NUMBER(SUBSTR(BUY_CODE, 5))), 0) + 1, 3, 0)
FROM SHOP_BUY
{executed in 1 msec}
20221019 12:24:39.574 [http-nio-8081-exec-1] INFO j.resultsettable -
|--------------------------------------------------------------|
|'buy_'||lpad(nvl(max(to_number(substr(buy_code,5))),0)+1,3,0) |
|--------------------------------------------------------------|
|BUY_002 |
|--------------------------------------------------------------|
20221019 12:24:39.575 [http-nio-8081-exec-1] DEBUG j.sqltiming - com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
1483. SELECT ITEM_CODE,CART_AMOUNT,TOTAL_PRICE
FROM SHOP_CART
WHERE CART_CODE IN (
'CART_004'
,
'CART_007'
)
{executed in 0 msec}
20221019 12:24:39.576 [http-nio-8081-exec-1] INFO j.resultsettable -
|----------|------------|------------|
|item_code |cart_amount |total_price |
|----------|------------|------------|
|ITEM_006 |10 |189000 |
|ITEM_007 |10 |98000 |
|----------|------------|------------|
20221019 12:24:39.577 [http-nio-8081-exec-1] DEBUG j.sqltiming - com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
1483. INSERT INTO SHOP_BUY(
BUY_CODE
, MEMBER_ID
, TOTAL_PRICE
)VALUES(
'BUY_002'
, 'aaa'
, 287000
)
{executed in 1 msec}
20221019 12:24:39.579 [http-nio-8081-exec-1] DEBUG j.sqltiming - com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
1483. INSERT INTO SHOP_BUY_DETAIL(
BUY_DETAIL_CODE
,ITEM_CODE
,BUY_CODE
,BUY_AMOUNT
)
SELECT 'BUY_002'||'_'||LPAD(0+1,2,0)
, 'ITEM_006'
, 'BUY_002'
, 10
FROM DUAL
UNION ALL
SELECT 'BUY_002'||'_'||LPAD(1+1,2,0)
, 'ITEM_007'
, 'BUY_002'
, 10
FROM DUAL
{executed in 1 msec}
실제 화면 결과
: 컨트롤러에서 리턴값을 구매하기 버튼클릭시,구매목록페이지로 이동시켰기 때문에 목록은 아직 나타나지않지만 그림만 보이며 디비를 확인하면 INSERT되어있는 것을 확인할 수 있다.
DB결과 조회
: SHOP_BUY테이블과 SHOP_BUY_DETAIL 테이블을 조회시, INSERT된것을 확인 가능하다.
오늘 실습내용
- 구매할 상품은 장바구니에서 삭제되어야한다.
- 단일 구매
: 상품상세정보페이지에서 구매버튼 클릭시 바로 구매되도록 만들기.
: 구매버튼 클릭시, 바로 구매되는 것이 아니라 buyInfo.html페이지로 바로 이동해야한다.
- 메뉴 나오기
- 주문내역 조회
- 매출관리
: 이전 만들어놓은 삭제쿼리문을 컨트롤러에서 불러온다.
cartService.deleteCarts(cartVO);
// 구매등록
@PostMapping("/insertBuy")
public String buyCart(String[] cartCodes, BuyVO buyVO,CartVO cartVO,Authentication authentication) {
//totalPrice,itemCode(들),수량(들) -> 데이터를 가져와야한다.
// 하지만!! cartCode(들)만 들고오면 위에 데이터들도 따라오게할 수 있다!!!
// cart테이블에가면 아이템코드 수량, 토탈프라이스 모두 있기때문에 cartCode만 알면 연결되 나머지 데이터들을 들고올 수 있다.
// cartCode(들)을 들고오는 방법은?
System.out.println("!@!!!!!!!!!!!!!!!!!!!@@@@" + cartCodes);// 콘솔확인시, CART_004,CART_007 -> 자스를 사용하지않아도 이런 식으로 데이터를 들고온다.
// 매개변수에서부터 배열 자료형으로 받으면(String[] cartCodes), 굳이 위에처럼 ,쉼표로 문자열을 자를 필요가 없다.
//for문을 돌려 하나씩빼서 콘솔 출력한다.
for(String e : cartCodes) {
System.out.println("@@@@@@@@@@@@@@@@@@@ " + e);
}
// buy_code 데이터 들고오기 : insert되어야하는 buy_code 조회
String buyCode = buyService.selectNextBuyCode();
//totalPrice,itemCode(들),cartAmount(들) 데이터는 어떻게 들고오냐
//위에 알고있는 cartCode를 이용해서 위 데이터를 쿼리문을 통해 가져온다. -> buy-mapper에서 만들어주기.
// 우리가 들고온 cartCode들을 cartVO에 넣어줘야한다.
// 이미 cartVo에는 리스트형태로 cartCodeList가 있는데, 이를 배열의 형태로 바꾸어 넣어준다.
List<String> cartCodeList = Arrays.asList(cartCodes);
cartVO.setCartCodeList(cartCodeList);
List<CartVO> cartList = buyService.getCartInfoForBuy(cartVO);
List<BuyDetailVO> buyDetailList = new ArrayList<>(); //아래 데이터 넣기위해서 미리 통만들기(변수선언)
//반복해서 itemCode와 amount값,totalPrice값 모두 for문돌려서 하나씩 빼기
int totalPrice =0;
for(CartVO cart : cartList) {
totalPrice = totalPrice + cart.getTotalPrice();
//아래처럼 만들어준 것을 위에 buydetailList 통에 넣어준다.
BuyDetailVO vo = new BuyDetailVO();
vo.setItemCode(cart.getItemCode());
vo.setBuyAmount(cart.getCartAmount());
buyDetailList.add(vo);
}
//memberID 데이터가져오기
User user = (User)authentication.getPrincipal();
// 위에서 부터 가져온 모든 데이터들을 BuyVO에서 setter를 이용해 데이터 넣어주기
buyVO.setBuyCode(buyCode);
buyVO.setMemberId(user.getUsername());
buyVO.setTotalPrice(totalPrice);
buyVO.setBuyDetailList(buyDetailList);// buyDetailVO 에서 itemCode,cartAmount값 가져오기.
//실제 구매실행 쿼리문
buyService.insertBuy(buyVO);
//구매한 장바구니는 목록에서 삭제
cartService.deleteCarts(cartVO);
return "content/buy/buy_list";
}