이제 DB 드라이버를 로드하고 닫아줄 모듈도 준비되었고, 데이터를 받아올 준비도 되었다. 구현체를 위한 인터페이스 제작도 완료되었다. 이제 준비해둔 작업물들로 직접 CRUD를 실행해줄 메인 Controller를 만들 차례이다.
이 앞의 작업들을 하는데 꼬박 이틀이 소요되었고, 프로젝트 마감 기한은 그 다음 이틀 후였으므로 시간이 얼마 남지 않은 상황이었다. 그래도 문서 작업을 미리 해둔 덕분에 구현 자체에는 큰 부담은 없었던 것 같다. 오히려 문서화가 정말 힘들었다...
처음 만든 컨트롤러는 각각의 인터페이스를 구현한 각자의 클래스로 만들었다. 그러나 이렇게 하게되니 main 구동페이지에서 하나로 합쳤을 때 드라이버 모듈이 4번 열리게 되는 기현상이 발생했다.... 지금은 후기로 이렇게 간단하게 쓰고 있지만 그 당시에는 모듈이 대체 왜 여러번 열리고 데이터가 여러번 돌아가는지 이유를 못 찾아서 4시간 동안 노트북만 붙들고 있었다....
아무튼 하나로 합친 컨트롤러는 앞선 네개의 인터페이스를 모두 다중 구현하고 데이터베이스 모듈을 상속받았다. 모든 구현체 메서드는 JUnit을 통해 테스트를 거쳤으며 성공 결과를 도출했다.
4개의 컨트롤러를 모두 합쳐서 코드가 정말 길다. 그래서 트랜잭션과 트리거가 발생한 코드만 몇개 추렸다.
추가적인 코드는 아래에서 볼 수 있다
https://github.com/bluewt129/Coffee_Kiosk/tree/controller
1. 게스트 로그인 시 게스트 코드를 자동으로 생성해주는 트리거
1) 1씩 증가하는 시퀀스 생성
2) 게스트 테이블에 INSERT하기 전에 G + 해당 날짜 월, 일 4자리 + 001(1부터 증가하는 시퀀스) 이런 형식으로 생성되는 게스트 코드를 만들었다. 뒷자리가 001처럼 3자리 이기 때문에 999까지 손님을 받을 수 있다
CREATE SEQUENCE GUEST_NUM_SEQ
START WITH 1
INCREMENT BY 1;
CREATE OR REPLACE TRIGGER TRIGGER_GUEST
BEFORE INSERT ON GUEST
FOR EACH ROW
BEGIN
:NEW.GUEST_CODE := 'G' || TO_NUMBER(TO_CHAR(SYSDATE, 'MMDD')) || LPAD(GUEST_NUM_SEQ.NEXTVAL, 3, '0');
END;
// (사용자 전용) 게스트 로그인. 로그인 없이 주문하는 사용자 전용 (자동 생성 트리거, 입력값 없음)
@Override
public int loginGuest() {
int rowNum = 0;
int logintype = 0;
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
String sql = " INSERT INTO GUEST g (ORDER_NUM) VALUES (NULL) ";
try {
conn = getConnection();
stmt = conn.prepareStatement(sql);
int insert = stmt.executeUpdate();
System.out.println("==================");
System.out.println("= 게스트 로그인 =");
System.out.println("==================");
if (insert > 0) {
System.out.println(">> 트리거 발동 : GUEST_CODE가 생성되었습니다");
System.out.println("CAFE : 게스트로 시작합니다");
rs = stmt.getGeneratedKeys();
if (rs.next()) {
rowNum = rs.getInt(1);
}
}
logintype = 8;
} catch (SQLException e) {
System.out.println("SYSTEM : 게스트 로그인 실패");
e.printStackTrace();
} finally {
closed(rs, stmt, conn);
}
return logintype;
}// (사용자 전용) 게스트 로그인. 로그인 없이 주문하는 사용자 전용 (자동 생성, 입력값 없음)
2. 신규 메뉴 등록시 재고가 자동으로 함께 등록되는 트랜잭션이다
- 메뉴 테이블과 재고 테이블을 따로 관리하기 때문에 쿼리문이 두번 이루어져야 하나의 작업이 완료된다고 볼 수 있다. 하나라도 실패할 시 롤백을 하기 위해 트랜잭션 옵션을 걸어주었다.
// 메뉴 신규 등록, 재고 등록 (트랜잭션)
@Override
public int setMenu(Menu_DTO dto) {
int rowNum = 0;
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
String sql = " INSERT INTO MENU m (MENU_NUM, MENU_TYPE, MENU_NAME, MENU_PRICE, MENU_DETAIL) "
+ " VALUES (MENU_NUM_SEQ.NEXTVAL, ?, ?, ?, ? ) ";
String sql2 = " INSERT INTO STOCK s (MENU_NUM, STOCK_CNT)VALUES (MENU_NUM_SEQ.CURRVAL, ? ) ";
try {
conn = getConnection();
conn.setAutoCommit(false);
System.out.println("SYSTEM : 트랜잭션 시작");
stmt = conn.prepareStatement(sql);
stmt = conn.prepareStatement(sql);
stmt.setInt(1, dto.getMenu_type());
stmt.setString(2, dto.getMenu_name());
stmt.setInt(3, dto.getMenu_price());
stmt.setString(4, dto.getMenu_detail());
rowNum += stmt.executeUpdate();
stmt.close();
stmt = conn.prepareStatement(sql2);
stmt.setInt(1, 100);
rowNum += stmt.executeUpdate();
conn.commit();
System.out.println("SYSTEM : 트랜잭션 완료 >> 커밋");
System.out.println("SYSTEM : " + dto.getMenu_name() + "(이/가) 정상적으로 등록되었습니다");
System.out.println(dto.getMenu_name() + "의 재고가 자동 보충되었습니다");
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
closed(rs, stmt, conn);
}
return rowNum;
}// 메뉴 신규 등록, 재고 등록 (트랜잭션)
'PROJECT > 커피숍' 카테고리의 다른 글
[토이/자바/JDBC] 커피숍 키오스크 만들기(12) : 입력 모듈 (0) | 2024.05.08 |
---|---|
[토이/자바/JDBC] 커피숍 키오스크 만들기(11) : JUnit Test (단위테스트) (0) | 2024.05.08 |
[토이/자바/JDBC] 커피숍 키오스크 만들기(8) : DAO (0) | 2024.05.08 |
[토이/자바/JDBC] 커피숍 키오스크 만들기(7) : DTO (0) | 2024.05.08 |
[토이/자바/JDBC] 커피숍 키오스크 만들기(6) : DB 모듈 구현 (0) | 2024.05.08 |