하나의 트랜잭션 안에서 여러 DML 작업이 수행되고,
그 중 하나라도 실패하면 전체를 롤백해야 한다.
ProductPage 중
insert() { // '등록'이라는 트랜잭션 시작
product insert() → 예외 전달
product_color insert() → 예외 전달
product_size insert() → 예외 전달
product_img insert() → 예외 전달
}
commit(); // 전부 성공 시 커밋
트랜잭션은 Connection 단위로 진행되기 때문에,
모든 DML은 반드시 같은 커넥션으로 묶어서 처리하기!
모든 DML은 하나의 Connection으로 묶기
DBManager.getConnection() → DAO마다 동일한 커넥션 전달
예외는 DAO 내부에서 catch하지 말고 throws로 바깥으로 던지기
바깥쪽(서비스 또는 페이지)에서 한 번에 try-catch
사용자에게는 이해할 수 있는 메시지만 보여주기
// MySQL에 상품 등록 관련 쿼리 수행
public void insert() {
// 트랜잭션이 적용되려면, 4개의 DAO가 모두 같은 Connection을 사용해야 함
Connection con = dbManager.getConnection();
try {
con.setAutoCommit(false); // start transaction 명령이 포함되어 있으므로 별도 호출 불필요
// 이 영역은 트랜잭션의 "시도(try)" 영역
// 이 중 하나라도 실패하면 catch 블록으로 이동 → rollback 수행
// 모두 성공하면 commit 수행
// Product 모델 인스턴스 생성 후, 상품 등록 데이터 세팅
Product product = new Product();
product.setSubcategory((SubCategory) cb_subcategory.getSelectedItem()); // FK (toString 오버라이딩 필요)
product.setProduct_name(t_product_name.getText());
product.setBrand(t_brand.getText());
product.setPrice(Integer.parseInt(t_price.getText()));
product.setDiscount(Integer.parseInt(t_discount.getText()));
product.setIntroduce(t_introduce.getText());
product.setDetail(t_detail.getText());
// 상품 등록
productDAO.insert(product);
// 등록된 상품의 최신 PK 값을 가져와 product에 세팅
int product_id = productDAO.selectRecentPk();
product.setProduct_id(product_id); // ★ 최신 PK 값을 product에 반영
// 상품에 연결된 색상 등록
List<Color> colorList = t_color.getSelectedValuesList();
for (Color color : colorList) {
ProductColor productColor = new ProductColor();
productColor.setProduct(product); // 어떤 상품에
productColor.setColor(color); // 어떤 색상을
productColorDAO.insert(productColor);
}
// 상품에 연결된 사이즈 등록
List<Size> sizeList = t_size.getSelectedValuesList();
for (Size size : sizeList) {
ProductSize productSize = new ProductSize();
productSize.setProduct(product); // 어떤 상품에
productSize.setSize(size); // 어떤 사이즈를
productSizeDAO.insert(productSize);
}
// 상품에 연결된 이미지 등록
for (int i = 0; i < newFiles.length; i++) {
File file = newFiles[i];
ProductImg productImg = new ProductImg();
productImg.setProduct(product);
productImg.setFilename(file.getName());
productImg.setProduct_img_id(productImg.getProduct().getProduct_id());
productImgDAO.insert(productImg);
}
con.commit(); // 모든 작업이 정상 수행됨 → 트랜잭션 확정
} catch (ProductException | ProductColorException | ProductSizeException | ProductImgException e) {
// 상품 등록 관련 커스텀 예외들
try {
con.rollback(); // 트랜잭션 되돌리기
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace(); // 개발자를 위한 디버깅 출력
JOptionPane.showMessageDialog(this, e.getMessage()); // 유저에게 메시지 전달
} catch (SQLException e) {
e.printStackTrace(); // JDBC 예외
} finally {
try {
con.setAutoCommit(true); // 커넥션 상태 복원
} catch (SQLException e) {
e.printStackTrace();
}
}
}