post: (userId, orders, totalPrice, callback) => { //유저의 주문을 DB에 저장하는 쿼리 : 테이블 간 관계 먼저 파악하는 것이 중요
const queryString1 = `INSERT INTO orders (user_id, total_price) VALUES (${userId} , ${totalPrice})`
const queryString2 = `INSERT INTO order_items (item_id, order_quantity, order_id) VALUES ?`
db.query(queryString1 , (error,result) => {
if(orders === undefined || orders.length === 0){
error = 1
callback(error, result)
}else{
const values = orders.map(order => { //values는 이차원 배열이어야 한다. 반드시..
order.orderId = result.insertId
console.log(order)
return Object.values(order)
})
db.query(queryString2,[values],(error,result) => { //여러개의 레코드 한번에 넣기 위해 [values]라고 작성한 것이다.
callback(error,result)
})
}
})
}
트랜잭션을 통해서도 처리를 할 수는 있겠지만.. 의도한 바와는 거리가 멀다.(스프린트 목적과도 거리있음)
각각의 테이블에 대해서 데이터를 삽입해야 하는 상황이고, orders 테이블의 id가 동시에 order_items에 들어가야 하는 상황이다.
그렇기 때문에 쿼리문이 2개 필요하여서 2개의 queryString을 선언,할당함.
단 order_items 테이블의 경우 여러 개의 행(여러 개의 상품을 하나의 주문건으로 묶어서 들어오는 경우)이 한꺼번에 들어오는 경우도 고려
그러므로 쿼리문 끝에 ? 를 사용하며, 이차원 배열을 사용하여야 한다.
문제는 orders 배열이 이차원 배열이 아니고, 객체를 요소로 갖는 배열이기 때문에, 배열 내의 객체를 모두 배열 타입으로 바꿔줘야 한다. 그래서 map 연산을 사용했던 것이며, 이를 이제 사용한다.
주문번호도 배열 안에 같이 들어가야 하는데 이는 result.inserId 값을 이용해 넣어야 한다.
이 때문에 db.query 문을 총 2번 써야 한다.
(insert into 쿼리문 날리고 나오는 result인자는 객체이며 이 안에 insertId 키 값이 있다.)
여기서 바로 문제가 생긴다. callback을 여기서 처리해주지 않으면 orders가 undefined 여도 그대로 코드가 실행이 되기 때문에 callbakc으로 반드시 에러를 캐치해ㅝ야 한다. 이는 프롬이스의 catch와 동일한 기능을 함.
controller 쪽에서도 에러 처리 시도했으나, 실패하였음.(여기서는 에러 처리 의미 없는게, model에서 코드 실행하고 나오는 그 결과가 에러인지 아닌지를 판단하는 것 같기 때문.. 추측해봄.)
따라서 총 2개의 콜백이 필요함.
첫번째 콜백은 에러가 나는 상황을 대비해서 에러객체에 truthy한 값을 할당해줘야 한다
사용자가 장바구니에 물건을 담은 상태에서만 주문이 가능해야 하므로, 즉, orders가 정의되어 있을 때만(or물건있을때만) 주문 가능해야 하므로 조건문을 분기해준 것이다.