일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 다중 카테고리 구현
- 대분류/중분류/소분류
- 고객센터 구현
- java
- 자바
- 프로그래머스
- ajax
- 일단_해보는거야
- 이메일로 인증코드 전송 구현
- SESSION
- 오라클
- jsp
- json
- 코딩
- 인증코드로 비밀번호 변경 구현
- MySQL
- js
- Spring MVC
- jakarta.mail
- Oracle
- jsp 프로젝트
- 로그인과 장바구니 구현
- 스프링
- Sts
- jquery
- Level 1
- MVC
- Spring
- 교보문고 따라하기
- 세션
감 잃지말고 개발하기
[JSP][MVC][MySQL] 도서 사이트에서 다중 카테고리 구현하기 #7. 데이터 수정하기 (2) 본문
지난 포스팅 "도서 사이트에서 다중 카테고리 구현하기 #6. 데이터 수정하기 (1)" 코드에 이어 그 뒷부분,
이번 구현 과정의 핵심 다중 트랜잭션 처리 메서드를 정리해 보도록 하겠다.
※ 참고 ※
해당 메서드는 BookDAO 클래스에서 작성한다.
♠ 이전 포스팅이 궁금하면 아래 링크를 클릭하세요 ♠
2023.06.26 - [JSP/MVC] - [JSP][MVC][MySQL] 도서 사이트에서 다중 카테고리 구현하기 #6. 데이터 수정하기 (1)
[JSP][MVC][MySQL] 도서 사이트에서 다중 카테고리 구현하기 #6. 데이터 수정하기 (1)
지난 포스팅 "도서 사이트에서 다중 카테고리 구현하기 #5. 데이터 출력하기 (2)"에서 서버에서 가져온 데이터를 도서 상세 페이지에 출력시키는 클라 딴 로직을 정리해 보았다. 다중 카테고리 구
persimmon-ary-stepbystep.tistory.com
목표
♠ 트랜잭션의 ACID 원칙을 준수하여 데이터베이스 작업을 수행할 수 있다.
♠ 중복된 코드를 최소화하고 가독성 있는 코드를 지향한다.
트랜잭션과 ACID 원칙
♠ 트랜잭션
DBMS(데이터베이스 관리 시스템)에서 수행되는 작업 또는 단위 작업을 의미한다.
DB에서 데이터를 CRUD(Create, Read, Update, Delete)하는 등의 작업을 수행할 때 트랜잭션으로 처리된다.
♠ ACID 원칙
ACID 원칙은 데이터베이스 트랜잭션의 일관성과 안전성을 보장하기 위한 원칙으로,
원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 지속성(Durability)을 의미한다.
☞ Atomicity(원자성)
트랜잭션은 "전부 성공"하거나 "전부 실패"해야 한다.
중간 단계에서 실패할 경우, 트랜잭션은 처음 상태로 복구된다.
☞ Consistency(일관성)
트랜잭션 전후에 DB는 일관된 상태여야 한다.
DB의 제약 조건이 유지되어야 한다.
☞ Isolation(독립성)
여러 트랜잭션이 동시에 실행되더라도, 각 트랜잭션은 다른 트랜잭션의 영향을 받지 않고 독립적으로 수행되어야 한다.
☞ Durability(영속성)
트랜잭션이 성공적으로 완료되면, 그 결과는 영구적으로 DB에 반영되어야 한다.
DB 작업 시 고려해야 할 점
코드를 작성하기에 앞서, 이번 구현의 DB 작업 시 도서 서브 카테고리 개수와 관련해 고려해야 할 점이 있다.
나는 도서 등록 페이지에서 특정 도서 한 권에 대한 서브 카테고리를 1개 이상 가질 수 있게 만들었다.
즉, 도서(book) 테이블과 서브 카테고리(booksubcatgy) 테이블은 일대다 관계이기 때문에 이에 따른 경우의 수를 생각해봐야 한다.
아래는 기존 DB 테이블에 저장된 서브 카테고리 개수와 관리자가 브라우저에서 변경한 서브 카테고리 개수에 따른 경우의 수를 나열한 후, 각각의 경우에 따라 필요한 DB 작업을 정리한 것이다.
아래의 경우에 따라 DB 작업을 처리할 것이다.
기존 DB 테이블에 저장된 서브 카테고리 개수를 A,
사용자가 도서 수정 페이지에서 변경한 서브 카테고리 개수를 B라고 하자.
경우 1. A와 B가 있을 때
1-1. A < B인 경우
변경할 서브 카테고리 개수가 기존 DB 테이블에 저장된 서브 카테고리 개수보다 많은 경우이다.
이런 경우, 다음과 같은 순서로 서브 카테고리 데이터를 수정할 수 있다.
- A 수만큼 변경할 서브 카테고리 데이터를 DB에 UPDATE 한다.
- 남은 개수(B-A)의 변경할 서브 카테고리 데이터를 DB에 INSERT 한다.
1-2. A > B인 경우
기존 DB 테이블에 저장된 서브 카테고리 개수가 변경할 서브 카테고리 개수보다 많은 경우이다.
이런 경우, 다음과 같은 순서로 서브 카테고리 데이터를 수정할 수 있다.
- B 수만큼 변경할 서브 카테고리 데이터를 DB에 UPDATE 한다.
- 남은 개수(A-B)의 기존 서브 카테고리 데이터를 DB에서 DELETE 한다.
1-3. A = B인 경우
기존 DB 테이블에 저장된 서브 카테고리 개수와 변경할 서브 카테고리 개수가 동일한 경우이다.
이런 경우, 다음과 같은 순서로 서브 카테고리 데이터를 수정할 수 있다.
- B 수만큼 변경할 서브 카테고리 데이터를 DB에 UPDATE 한다.
경우 2. A는 있지만 B가 없을 때
기존 DB 테이블에 저장된 서브 카테고리 데이터는 있지만 변경할 서브 카테고리 데이터가 존재하지 않는 경우이다.
이런 경우, 다음과 같은 순서로 서브 카테고리 데이터를 수정할 수 있다.
- A 수만큼의 기존 서브 카테고리 데이터를 DB에서 DELETE 한다.
경우 3. A는 없지만 B가 있을 때
기존 DB 테이블에 저장된 서브 카테고리 데이터는 존재하지 않지만 변경할 서브 카테고리 데이터는 존재하는 경우이다.
이런 경우, 다음과 같은 순서로 서브 카테고리 데이터를 수정할 수 있다.
- B 수만큼의 변경할 서브 카테고리 데이터를 DB에 INSERT 한다.
경우 4. A와 B 모두 없을 때
기존 DB 테이블에 저장된 서브 카테고리 데이터 및 변경할 서브 카테고리 데이터 모두 존재하지 않는 경우이다.
이런 경우, 서브 카테고리 데이터 관련한 트랜잭션을 처리할 필요가 없다.
메서드 처리 흐름
위의 경우의 수를 고려하면서 DAO 클래스에서의 메서드 처리 흐름을 생각해 보자.
1. 메서드가 호출되면 특정 도서 정보가 UPDATE 된다(book 테이블).
- 위의 수행 과정에서 예외가 발생할 시 무조건 ROLLBACK 되어야 하며, 그 이후의 booksubcatgy 테이블에 대한 그 어떤 트랜잭션은 수행되지 않아야 한다.
2. 1번의 트랜잭션이 성공적으로 수행되었을 때 특정 도서 한 권에 대한 서브 카테고리 정보가 UPDATE 된다(booksubcatgy 테이블).
- 경우 1 ~ 4에 따라 필요한 작업이 수행된다.
- 2번의 트랜잭션을 수행하는 과정에 있어 예외가 발생할 시 booksubcatgy 테이블 및 book 테이블 모두 ROLLBACK 되어야 한다.
3. 두 테이블에 대한 모든 트랜잭션이 정상적으로 수행되었을 때 COMMIT 된다.
- 해당 작업은 Service 클래스에서 구현해 놓았다.
메서드 작성
위의 메서드 처리 흐름을 토대로 본격적으로 메서드를 작성해 보자.
해당 메서드는 Service 클래스에서 던져준 Book 객체와 서브 카테고리 배열을 매개변수로 받아 처리할 것이다.
1. book 테이블 처리
1-1. book 테이블 UPDATE
☞ 처리
book 테이블에서 특정 도서의 정보를 UPDATE 하는 작업을 작성한다.
☞ 조건
예외 발생 시 무조건 ROLLBACK 되어야 하며, 그 이후의 booksubcatgy 테이블에 대한 그 어떤 트랜잭션은 수행되지 않아야 한다.
☞ 변수
기존 DB에 있는 서브 카테고리 데이터 개수를 저장할 변수와 변경할 서브 카테고리 데이터 개수를 저장할 변수가 필요하다.
- List<Integer> existingSubcategoriesList = null;
- booksubcatgy 테이블 관련한 DML 구문에 필요한 값을 가져오기 위해 필요한 변수이다.
- booksubcatgy 테이블에서 특정 도서에 해당하는 서브 카테고리 데이터의 PK값을 List형으로 저장한다.
- 이 PK값으로 특정 서브 카테고리 데이터를 UPDATE 할 것이다.
- int existingSubcategoriesDB = 0;
- 기존 DB에 저장된 서브 카테고리 데이터 개수를 저장한다.
- int updatedSubcategories = sub_catgy_arr.length;
- 변경할 서브 카테고리 데이터의 개수(길이)를 저장한다.
- int updateCount = 0;
- DB 작업의 처리결과를 저장한다.
☞ 코드
public int updateBook(Book book, int[] sub_catgy_arr) throws SQLException, Exception {
List<Integer> existingSubcategoriesList = null;
int existingSubcategoriesDB = 0;
int updatedSubcategories = sub_catgy_arr.length;
int updateCount = 0;
String update_sql = "UPDATE jspbookshop.book "
+ "SET b_name=?, b_writer=?, b_translator=?, b_publisher=?, b_bc_code=?, "
+ "b_price=?, b_image=?, b_page=?, b_publish_date=?, b_content=? "
+ "where b_id=?";
try(PreparedStatement pstmt = conn.prepareStatement(update_sql)) {
pstmt.setString(1, book.getB_name());
pstmt.setString(2, book.getB_writer());
pstmt.setString(3, book.getB_translator());
pstmt.setString(4, book.getB_publisher());
pstmt.setInt(5, book.getB_bc_code());
pstmt.setInt(6, book.getB_price());
pstmt.setString(7, book.getB_image());
pstmt.setInt(8, book.getB_page());
pstmt.setString(9, book.getB_publish_date());
pstmt.setString(10, book.getB_content());
pstmt.setInt(11, book.getB_id());
if(pstmt.executeUpdate() > 0) {
// DML 구문이 잘 처리된 경우
// booksubcatgy 테이블 수정 처리
} else {
// 도서가 저장이 안된 경우
rollback(conn);
}
} catch(Exception e) {
System.out.println(" updateBook ERROR1 pstmt 처리 도중 에러 : "+e);
}
return updateCount;
}
1-2. 특정 도서의 서브 카테고리 확인
☞ 처리
booksubcatgy 테이블에서 작업을 수행하기 위해 도서 아이디(PK)에 따른 서브 카테고리 데이터의 PK값을 가져오는 작업을 작성한다.
☞ 조건
book 테이블의 DML 구문이 정상적으로 수행된 경우 해당 작업이 이루어지도록 if문 안에 작성한다.
☞ while(rs.next()) { }
while() 문을 돌면서 레코드가 존재할 때,
변수 existingSubcategoriesList엔 첫 번째 열의 값을 저장하고, 변수 existingSubcategoriesDB의 값을 1 증가한다.
최종적으로 변수 existingSubcategoriesList엔 특정 도서의 서브 카테고리 데이터의 PK값이 List형으로 저장될 것이다.
☞ 코드
String select_sql = "SELECT bsc_id FROM jspbookshop.booksubcatgy WHERE bsc_b_id = ?";
try (PreparedStatement subSelectPstmt = conn.prepareStatement(select_sql)) {
subSelectPstmt.setInt(1, book.getB_id());
try(ResultSet rs = subSelectPstmt.executeQuery()) {
existingSubcategoriesList = new ArrayList<Integer>();
while (rs.next()) {
existingSubcategoriesDB++;
existingSubcategoriesList.add(rs.getInt(1));
}
} catch (Exception e) {
System.out.println(" updateBook ERROR3 rs 처리 도중 에러 : "+e);
}
} catch (Exception e) {
System.out.println(" updateBook ERROR2 subSelectPstmt 처리 도중 에러 : "+e);
}
2. booksubcatgy 테이블 처리
☞ 처리
위의 DB 작업 시 고려해야 할 점 과 함께 살펴보면서 처리한다.
☞ 조건
- book 테이블의 UPDATE 작업이 수행된 경우 실행한다.
- 경우 1 ~ 4에 따라 필요한 작업을 작성한다.
- 모든 트랜잭션을 수행하는 과정에 있어 예외가 발생할 시 booksubcatgy 테이블 및 book 테이블 모두 ROLLBACK 되어야 한다.
☞ 코드
if(existingSubcategoriesList != null) {
/* 경우 1. */
if(existingSubcategoriesDB > 0 && updatedSubcategories > 0) {
}
/* 경우 2. */
else if(existingSubcategoriesDB > 0 && updatedSubcategories <= 0 ) {
}
/* 경우 3. */
else if (existingSubcategoriesDB == 0 && updatedSubcategories > 0){
}
/* 경우 4. */
else {
}
}
2-1. 경우 1. 에 따른 booksubcatgy 테이블 처리
☞ 처리
기존의 서브 카테고리(DB) 데이터 및 변경할 서브 카테고리 데이터가 있는 경우이다.
3가지 경우의 수가 세부적으로 존재하므로 각각의 경우에 따라 필요한 작업을 작성한다.
☞ 조건
첫 번째 if문 안에 작성한다.
☞ 코드
/* 경우 1. */
if(existingSubcategoriesDB > 0 && updatedSubcategories > 0) {
/* 경우 1-1. 변경할 서브 카테고리 데이터(B)가 더 많은 경우 */
if(updatedSubcategories-existingSubcategoriesDB > 0) {
// 1. 기존의 서브 카테고리(DB) 개수(A)만큼 수정
update_sql = "UPDATE jspbookshop.booksubcatgy "
+ "SET bsc_bc_code = ? "
+ "WHERE bsc_b_id = ? "
+ "AND bsc_id = ?";
try(PreparedStatement subUpdatePstmt = conn.prepareStatement(update_sql)) {
for(int i=0; i<existingSubcategoriesDB; i++) {
subUpdatePstmt.setInt(1, sub_catgy_arr[i]);
subUpdatePstmt.setInt(2, book.getB_id());
subUpdatePstmt.setInt(3, existingSubcategoriesList.get(i));
updateCount += subUpdatePstmt.executeUpdate();
}
// 2. (B-A)만큼 INSERT
update_sql = "INSERT INTO jspbookshop.booksubcatgy(bsc_b_id, bsc_bc_code) VALUES(?, ?)";
try(PreparedStatement subInsertPstmt = conn.prepareStatement(update_sql)) {
subInsertPstmt.setInt(1, book.getB_id());
for(int i=existingSubcategoriesDB; i<updatedSubcategories; i++) {
subInsertPstmt.setInt(2, sub_catgy_arr[i]);
updateCount += subInsertPstmt.executeUpdate();
}
} catch (Exception e) {
System.out.println(" updateBook ERROR6 subInsertPstmt 처리 도중 에러 : "+e);
}
} catch (Exception e) {
System.out.println(" updateBook ERROR5 subUpdatePstmt 처리 도중 에러 : "+e);
}
}
/* 경우 1-2. 기존의 서브 카테고리(DB) 데이터(A)가 더 많은 경우 */
else if(updatedSubcategories-existingSubcategoriesDB < 0){
// 1. 변경할 서브 카테고리 데이터 길이(B)만큼 수정
update_sql = "UPDATE jspbookshop.booksubcatgy "
+ "SET bsc_bc_code = ? "
+ "WHERE bsc_b_id = ? "
+ "AND bsc_id = ?";
try(PreparedStatement subUpdatePstmt = conn.prepareStatement(update_sql)) {
for(int i=0; i<updatedSubcategories; i++) {
subUpdatePstmt.setInt(1, sub_catgy_arr[i]);
subUpdatePstmt.setInt(2, book.getB_id());
subUpdatePstmt.setInt(3, existingSubcategoriesList.get(i));
updateCount += subUpdatePstmt.executeUpdate();
}
// 2. 남은 기존 서브 카테고리(DB) 데이터 DELETE
update_sql = "DELETE FROM jspbookshop.booksubcatgy "
+ "WHERE bsc_id = ? "
+ "AND bsc_b_id = ?";
try(PreparedStatement subDeletePstmt = conn.prepareStatement(update_sql)) {
for(int i=updatedSubcategories; i<existingSubcategoriesDB; i++) {
subDeletePstmt.setInt(1, existingSubcategoriesList.get(i));
subDeletePstmt.setInt(2, book.getB_id());
updateCount += subDeletePstmt.executeUpdate();
}
} catch (Exception e) {
System.out.println(" updateBook ERROR6 subDeletePstmt 처리 도중 에러 : "+e);
}
} catch (Exception e) {
System.out.println(" updateBook ERROR5 subUpdatePstmt 처리 도중 에러 : "+e);
}
}
/* 경우 1-3. 데이터 개수가 동일한 경우 */
else {
update_sql = "UPDATE jspbookshop.booksubcatgy "
+ "SET bsc_bc_code = ? "
+ "WHERE bsc_b_id = ? "
+ "AND bsc_id = ?";
try(PreparedStatement subUpdatePstmt = conn.prepareStatement(update_sql)) {
for(int i=0; i<updatedSubcategories; i++) {
subUpdatePstmt.setInt(1, sub_catgy_arr[i]);
subUpdatePstmt.setInt(2, book.getB_id());
subUpdatePstmt.setInt(3, existingSubcategoriesList.get(i));
updateCount += subUpdatePstmt.executeUpdate();
}
} catch (Exception e) {
System.out.println(" updateBook ERROR5 subUpdatePstmt 처리 도중 에러 : "+e);
}
}
}
2-2. 경우 2. 에 따른 booksubcatgy 테이블 처리
☞ 처리
기존의 서브 카테고리(DB) 데이터(A)는 존재하지만 변경할 서브 카테고리 데이터(B)가 없는 경우이다.
A 수만큼의 기존 서브 카테고리 데이터를 DB에서 DELETE 하는 작업을 작성한다.
☞ 조건
두 번째 else-if문 안에 작성한다.
☞ 코드
/* 경우 2. */
else if(existingSubcategoriesDB > 0 && updatedSubcategories <= 0 ) {
String delete_sql = "DELETE FROM jspbookshop.booksubcatgy "
+ "WHERE bsc_id = ? AND bsc_b_id = ?";
try (PreparedStatement subDeletePstmt = conn.prepareStatement(delete_sql)) {
// 카테고리 데이터 배열 순회 및 DELETE
for (int i=0; i<existingSubcategoriesDB; i++) {
subDeletePstmt.setInt(1, existingSubcategoriesList.get(i));
subDeletePstmt.setInt(2, book.getB_id());
updateCount += subDeletePstmt.executeUpdate();
}
} catch (Exception e) {
System.out.println(" updateBook ERROR4 subDeletePstmt 처리 도중 에러 : "+e);
}
}
2-3. 경우 3. 에 따른 booksubcatgy 테이블 처리
☞ 처리
기존의 서브 카테고리(DB) 데이터(A)는 존재하지 않지만 변경할 서브 카테고리 데이터(B)는 존재하는 경우이다.
B 수만큼의 변경할 서브 카테고리 데이터를 DB에 INSERT 하는 작업을 작성한다.
☞ 조건
세 번째 else-if문 안에 작성한다.
☞ 코드
/* 경우 3. */
else if (existingSubcategoriesDB == 0 && updatedSubcategories > 0){
String insert_sql = "INSERT INTO jspbookshop.booksubcatgy(bsc_b_id, bsc_bc_code) VALUES(?, ?)";
try(PreparedStatement subInsertPstmt = conn.prepareStatement(insert_sql)) {
for(int i=0; i<updatedSubcategories; i++) {
subInsertPstmt.setInt(1, book.getB_id());
subInsertPstmt.setInt(2, sub_catgy_arr[i]);
updateCount += subInsertPstmt.executeUpdate();
}
} catch (Exception e) {
System.out.println(" updateBook ERROR4 subInsertPstmt 처리 도중 에러 : "+e);
}
}
2-4. 경우 4. 에 따른 booksubcatgy 테이블 처리
☞ 처리
기존의 서브 카테고리(DB) 데이터(A) 및 변경할 서브 카테고리 데이터(B) 모두 존재하지 않는 경우이다.
변수 updateCount에 1을 저장시킨다.
☞ 조건
마지막 else문 안에 작성한다.
☞ 코드
else {
updateCount = 1;
}
▼ 전체 코드
public int updateBook(Book book, int[] sub_catgy_arr) throws SQLException, Exception {
System.out.println(" B.DAO : updateBook() 호출");
List<Integer> existingSubcategoriesList = null;
int existingSubcategoriesDB = 0;
int updatedSubcategories = sub_catgy_arr.length;
int updateCount = 0;
String update_sql = "UPDATE jspbookshop.book "
+ "SET b_name=?, b_writer=?, b_translator=?, b_publisher=?, b_bc_code=?, "
+ "b_price=?, b_image=?, b_page=?, b_publish_date=?, b_content=? "
+ "where b_id=?";
try(PreparedStatement pstmt = conn.prepareStatement(update_sql)) {
pstmt.setString(1, book.getB_name());
pstmt.setString(2, book.getB_writer());
pstmt.setString(3, book.getB_translator());
pstmt.setString(4, book.getB_publisher());
pstmt.setInt(5, book.getB_bc_code());
pstmt.setInt(6, book.getB_price());
pstmt.setString(7, book.getB_image());
pstmt.setInt(8, book.getB_page());
pstmt.setString(9, book.getB_publish_date());
pstmt.setString(10, book.getB_content());
pstmt.setInt(11, book.getB_id());
if(pstmt.executeUpdate() > 0) {
String select_sql = "SELECT bsc_id FROM jspbookshop.booksubcatgy WHERE bsc_b_id = ?";
try (PreparedStatement subSelectPstmt = conn.prepareStatement(select_sql)) {
subSelectPstmt.setInt(1, book.getB_id());
try(ResultSet rs = subSelectPstmt.executeQuery()) {
existingSubcategoriesList = new ArrayList<Integer>();
while (rs.next()) {
existingSubcategoriesDB++;
existingSubcategoriesList.add(rs.getInt(1));
}
} catch (Exception e) {
System.out.println(" updateBook ERROR3 rs 처리 도중 에러 : "+e);
}
} catch (Exception e) {
System.out.println(" updateBook ERROR2 subSelectPstmt 처리 도중 에러 : "+e);
}
} else {
// 도서가 저장이 안된 경우
rollback(conn);
}
} catch (Exception e) {
System.out.println(" updateBook ERROR1 pstmt 처리 도중 에러 : "+e);
}
System.out.println("updatedSubcategories : "+updatedSubcategories);
System.out.println("existingSubcategoriesDB : "+existingSubcategoriesDB);
/* 위의 UPDATE가 잘 된 경우 실행 */
if(existingSubcategoriesList != null) {
/* 경우 1. */
if(existingSubcategoriesDB > 0 && updatedSubcategories > 0) {
System.out.println("기존의 서브 분류(DB) 데이터 및 변경할 서브 분류 데이터가 있습니다.");
/* 경우 1-1. 변경할 서브 분류 데이터(B)가 더 많은 경우 */
if(updatedSubcategories-existingSubcategoriesDB > 0) {
System.out.println("변경할 서브 분류 데이터가 더 많은 경우");
// 1. 기존의 서브 분류(DB) 개수(A)만큼 수정
update_sql = "UPDATE jspbookshop.booksubcatgy "
+ "SET bsc_bc_code = ? "
+ "WHERE bsc_b_id = ? "
+ "AND bsc_id = ?";
try(PreparedStatement subUpdatePstmt = conn.prepareStatement(update_sql)) {
for(int i=0; i<existingSubcategoriesDB; i++) {
subUpdatePstmt.setInt(1, sub_catgy_arr[i]);
subUpdatePstmt.setInt(2, book.getB_id());
subUpdatePstmt.setInt(3, existingSubcategoriesList.get(i));
updateCount += subUpdatePstmt.executeUpdate();
}
// 2. (B-A)만큼 INSERT
update_sql = "INSERT INTO jspbookshop.booksubcatgy(bsc_b_id, bsc_bc_code) VALUES(?, ?)";
try(PreparedStatement subInsertPstmt = conn.prepareStatement(update_sql)) {
subInsertPstmt.setInt(1, book.getB_id());
for(int i=existingSubcategoriesDB; i<updatedSubcategories; i++) {
subInsertPstmt.setInt(2, sub_catgy_arr[i]);
updateCount += subInsertPstmt.executeUpdate();
}
} catch (Exception e) {
System.out.println(" updateBook ERROR6 subInsertPstmt 처리 도중 에러 : "+e);
}
} catch (Exception e) {
System.out.println(" updateBook ERROR5 subUpdatePstmt 처리 도중 에러 : "+e);
}
}
/* 경우 1-2. 기존의 서브 분류(DB) 데이터(A)가 더 많은 경우 */
else if(updatedSubcategories-existingSubcategoriesDB < 0){
System.out.println("기존의 서브 분류(DB) 데이터가 더 많은 경우");
// 1. 변경할 서브 분류 데이터 길이(B)만큼 수정
update_sql = "UPDATE jspbookshop.booksubcatgy "
+ "SET bsc_bc_code = ? "
+ "WHERE bsc_b_id = ? "
+ "AND bsc_id = ?";
try(PreparedStatement subUpdatePstmt = conn.prepareStatement(update_sql)) {
for(int i=0; i<updatedSubcategories; i++) {
subUpdatePstmt.setInt(1, sub_catgy_arr[i]);
subUpdatePstmt.setInt(2, book.getB_id());
subUpdatePstmt.setInt(3, existingSubcategoriesList.get(i));
updateCount += subUpdatePstmt.executeUpdate();
}
// 2. 남은 기존 서브 분류(DB) 데이터 DELETE
update_sql = "DELETE FROM jspbookshop.booksubcatgy "
+ "WHERE bsc_id = ? "
+ "AND bsc_b_id = ?";
try(PreparedStatement subDeletePstmt = conn.prepareStatement(update_sql)) {
for(int i=updatedSubcategories; i<existingSubcategoriesDB; i++) {
subDeletePstmt.setInt(1, existingSubcategoriesList.get(i));
subDeletePstmt.setInt(2, book.getB_id());
updateCount += subDeletePstmt.executeUpdate();
}
} catch (Exception e) {
System.out.println(" updateBook ERROR6 subDeletePstmt 처리 도중 에러 : "+e);
}
} catch (Exception e) {
System.out.println(" updateBook ERROR5 subUpdatePstmt 처리 도중 에러 : "+e);
}
}
/* 경우 1-3. 데이터 개수가 동일한 경우 */
else {
System.out.println("데이터 개수가 동일한 경우");
update_sql = "UPDATE jspbookshop.booksubcatgy "
+ "SET bsc_bc_code = ? "
+ "WHERE bsc_b_id = ? "
+ "AND bsc_id = ?";
try(PreparedStatement subUpdatePstmt = conn.prepareStatement(update_sql)) {
for(int i=0; i<updatedSubcategories; i++) {
subUpdatePstmt.setInt(1, sub_catgy_arr[i]);
subUpdatePstmt.setInt(2, book.getB_id());
subUpdatePstmt.setInt(3, existingSubcategoriesList.get(i));
updateCount += subUpdatePstmt.executeUpdate();
}
} catch (Exception e) {
System.out.println(" updateBook ERROR5 subUpdatePstmt 처리 도중 에러 : "+e);
}
}
}
/* 경우 2. */
else if(existingSubcategoriesDB > 0 && updatedSubcategories <= 0 ) {
System.out.println("기존의 서브 분류(DB) 데이터가 있지만 변경할 서브 분류 데이터가 없습니다.");
String delete_sql = "DELETE FROM jspbookshop.booksubcatgy "
+ "WHERE bsc_id = ? AND bsc_b_id = ?";
try (PreparedStatement subDeletePstmt = conn.prepareStatement(delete_sql)) {
// 카테고리 데이터 배열 순회 및 DELETE
for (int i=0; i<existingSubcategoriesDB; i++) {
subDeletePstmt.setInt(1, existingSubcategoriesList.get(i));
subDeletePstmt.setInt(2, book.getB_id());
updateCount += subDeletePstmt.executeUpdate();
}
} catch (Exception e) {
System.out.println(" updateBook ERROR4 subDeletePstmt 처리 도중 에러 : "+e);
}
}
/* 경우 3. */
else if (existingSubcategoriesDB == 0 && updatedSubcategories > 0){
System.out.println("기존의 서브 분류(DB) 데이터는 없지만 변경할 서브 분류 데이터가 있습니다.");
String insert_sql = "INSERT INTO jspbookshop.booksubcatgy(bsc_b_id, bsc_bc_code) VALUES(?, ?)";
try(PreparedStatement subInsertPstmt = conn.prepareStatement(insert_sql)) {
for(int i=0; i<updatedSubcategories; i++) {
subInsertPstmt.setInt(1, book.getB_id());
subInsertPstmt.setInt(2, sub_catgy_arr[i]);
updateCount += subInsertPstmt.executeUpdate();
}
} catch (Exception e) {
System.out.println(" updateBook ERROR4 subInsertPstmt 처리 도중 에러 : "+e);
}
}
/* 경우 4. */
else {
System.out.println("기존의 서브 분류(DB) 및 변경할 서브 분류 데이터가 없습니다.");
updateCount = 1;
}
}
System.out.println(" B.DAO : updateBook() 종료");
return updateCount;
}
서버 및 DB 확인
지금까지의 작업이 클라 딴 - 서버 딴에서 잘 처리되는지 서버 콘솔 및 DB 조회로 확인해 보자.
DB book 테이블에 다음의 도서가 저장되어 있다.
해당 도서 아이디는 98, 메인 분류에는 1개, 서브 분류에는 1개의 데이터가 저장되어 있다.
아래의 도서 정보를 수정해 보자.
경우 1. A와 B가 있을 때
1-1. A < B인 경우
서브 분류에 3개의 데이터를 추가해 주었다.
▼ 서버 콘솔 출력 결과
▼ DB 조회 결과
1-2. A > B인 경우
기존 서브 분류에서 2개를 삭제해 주었다.
▼ 서버 콘솔 출력 결과
▼ DB 조회 결과
1-3. A = B인 경우
기존 서브 분류 데이터를 다른 분류로 변경해 주었다.
▼ 서버 콘솔 출력 결과
▼ DB 조회 결과
경우 2. A는 있지만 B가 없을 때
기존 서브 분류 데이터를 모두 삭제해 주었다.
▼ 서버 콘솔 출력 결과
경우 3. A는 없지만 B가 있을 때
새로운 서브 카테고리를 추가해 주었다.
▼ 서버 콘솔 출력 결과
▼ DB 조회 결과
경우 4. A와 B 모두 없을 때
서브 카테고리가 없는 도서의 다른 정보를 변경해 주었다.
▼ 기존 도서 정보
▼ 변경한 도서 정보
▼ 서버 콘솔 출력 결과
▼ DB 조회 결과
구현에 필요한 DAO 클래스의 메서드가 모두 작성되었다.
다음 포스팅에서는 위의 메서드를 가독성 있게 정리해봄으로써 도서 정보를 수정하는 서버 딴 로직을 마치도록 하겠다.
#7. 데이터 수정하기 (2) 끝.
'JSP > MVC' 카테고리의 다른 글
[JSP][MVC][MySQL] 도서 목록 페이지에서 필터링 구현하기 #2. 클라 딴 (1) (0) | 2023.08.03 |
---|---|
[JSP][MVC][MySQL] 도서 목록 페이지에서 필터링 구현하기 #1. 구현 틀 잡기 (0) | 2023.08.02 |
[JSP][MVC][MySQL] 도서 사이트에서 다중 카테고리 구현하기 #8. 데이터 수정하기 (3) (마지막) (0) | 2023.06.30 |
[JSP][MVC][MySQL] 도서 사이트에서 다중 카테고리 구현하기 #6. 데이터 수정하기 (1) (0) | 2023.06.26 |
[JSP][MVC][MySQL] 도서 사이트에서 다중 카테고리 구현하기 #5. 데이터 출력하기 (2) (0) | 2023.06.13 |
[JSP][MVC][MySQL] 도서 사이트에서 다중 카테고리 구현하기 #4. 데이터 출력하기 (1) (0) | 2023.06.12 |