Ⅸ. article DELETE 기능 구현
1. article DELETE 기능 구현
- 그냥 article delete를 하면 삭제할 수 있지만, 잘못되면 다른 곳을 제거할 수 있는 위험이 있음
→ 그래서 있을 경우에 제거될 수 있도록 설정해야 함
- SQLErrorException, DBUtil과 SecSql 추가 및 이를 이용해 article DELETE를 구현
- SQLErrorException.java에 다음과 같이 입력
package exam_Exception;
public class SQLErrorException extends RuntimeException {
private Exception origin;
public SQLErrorException(String message, Exception origin) {
super(message);
this.origin = origin;
}
public Exception getOrigin() {
return origin;
}
}
- DBUtil.java에 다음과 같이 입력
package exam_Util;
import java.sql.*;
import java.util.*;
import exam_Exception.SQLErrorException;
public class DBUtil {
public static Map<String, Object> selectRow(Connection dbConn, SecSql sql) {
List<Map<String, Object>> rows = selectRows(dbConn, sql);
if (rows.size() == 0) {
return new HashMap<>();
}
return rows.get(0);
}
public static List<Map<String, Object>> selectRows(Connection dbConn, SecSql sql) throws SQLErrorException {
List<Map<String, Object>> rows = new ArrayList<>();
PreparedStatement stmt = null;
ResultSet rs = null;
try {
stmt = sql.getPreparedStatement(dbConn);
rs = stmt.executeQuery();
ResultSetMetaData metaData = rs.getMetaData();
int columnSize = metaData.getColumnCount();
while (rs.next()) {
Map<String, Object> row = new HashMap<>();
for (int columnIndex = 0; columnIndex < columnSize; columnIndex++) {
String columnName = metaData.getColumnName(columnIndex + 1);
Object value = rs.getObject(columnName);
if (value instanceof Long) {
int numValue = (int) (long) value;
row.put(columnName, numValue);
} else if (value instanceof Timestamp) {
String dateValue = value.toString();
dateValue = dateValue.substring(0, dateValue.length() - 2);
row.put(columnName, dateValue);
} else {
row.put(columnName, value);
}
}
rows.add(row);
}
} catch (SQLException e) {
throw new SQLErrorException("SQL 예외, SQL : " + sql, e);
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
throw new SQLErrorException("SQL 예외, rs 닫기, SQL : " + sql, e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
throw new SQLErrorException("SQL 예외, stmt 닫기, SQL : " + sql, e);
}
}
}
return rows;
}
public static int selectRowIntValue(Connection dbConn, SecSql sql) {
Map<String, Object> row = selectRow(dbConn, sql);
for (String key : row.keySet()) {
return (int) row.get(key);
}
return -1;
}
public static String selectRowStringValue(Connection dbConn, SecSql sql) {
Map<String, Object> row = selectRow(dbConn, sql);
for (String key : row.keySet()) {
return (String) row.get(key);
}
return "";
}
public static boolean selectRowBooleanValue(Connection dbConn, SecSql sql) {
Map<String, Object> row = selectRow(dbConn, sql);
for (String key : row.keySet()) {
return ((int) row.get(key)) == 1;
}
return false;
}
public static int insert(Connection dbConn, SecSql sql) {
int id = -1;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
stmt = sql.getPreparedStatement(dbConn);
stmt.executeUpdate();
rs = stmt.getGeneratedKeys();
if (rs.next()) {
id = rs.getInt(1);
}
} catch (SQLException e) {
throw new SQLErrorException("SQL 예외, SQL : " + sql, e);
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
throw new SQLErrorException("SQL 예외, rs 닫기, SQL : " + sql, e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
throw new SQLErrorException("SQL 예외, stmt 닫기, SQL : " + sql, e);
}
}
}
return id;
}
public static int update(Connection dbConn, SecSql sql) {
int affectedRows = 0;
PreparedStatement stmt = null;
try {
stmt = sql.getPreparedStatement(dbConn);
affectedRows = stmt.executeUpdate();
} catch (SQLException e) {
throw new SQLErrorException("SQL 예외, SQL : " + sql, e);
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
throw new SQLErrorException("SQL 예외, stmt 닫기, SQL : " + sql, e);
}
}
}
return affectedRows;
}
public static int delete(Connection dbConn, SecSql sql) {
return update(dbConn, sql);
}
}
- SecSql.java에 다음과 같이 입력
package exam_Util;
import java.sql.*;
import java.util.*;
public class SecSql {
private StringBuilder sqlBuilder;
private List<Object> datas;
@Override
public String toString() {
return "sql=" + getFormat() + ", data=" + datas;
}
public SecSql() {
sqlBuilder = new StringBuilder();
datas = new ArrayList<>();
}
public boolean isInsert() {
return getFormat().startsWith("INSERT");
}
public SecSql append(Object... args) {
if (args.length > 0) {
String sqlBit = (String) args[0];
sqlBuilder.append(sqlBit + " ");
}
for (int i = 1; i < args.length; i++) {
datas.add(args[i]);
}
return this;
}
public PreparedStatement getPreparedStatement(Connection dbConn) throws SQLException {
PreparedStatement stmt = null;
if (isInsert()) {
stmt = dbConn.prepareStatement(getFormat(), Statement.RETURN_GENERATED_KEYS);
} else {
stmt = dbConn.prepareStatement(getFormat());
}
for (int i = 0; i < datas.size(); i++) {
Object data = datas.get(i);
int parameterIndex = i + 1;
if (data instanceof Integer) {
stmt.setInt(parameterIndex, (int) data);
} else if (data instanceof String) {
stmt.setString(parameterIndex, (String) data);
}
}
return stmt;
}
public String getFormat() {
return sqlBuilder.toString();
}
public static SecSql from(String sql) {
return new SecSql().append(sql);
}
}
- 그 후, Main.java에 다음과 같이 입력
package exam;
import java.sql.*;
import java.util.*;
import exam_Util.DBUtil;
import exam_Util.SecSql;
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Scanner sc = new Scanner(System.in);
System.out.println("==프로그램 시작==");
int lastArticleId = 0;
while (true) {
System.out.printf("명령어 ) ");
String cmd = sc.nextLine().trim();
if (cmd.equals("exit")) {
System.out.println("===종료===");
break;
}
if (cmd.equals("article write")) {
System.out.println("== 게시물 작성 ==");
int id = lastArticleId + 1;
System.out.printf("제목 : ");
String title = sc.nextLine();
System.out.printf("내용 : ");
String body = sc.nextLine();
System.out.printf("%d번글이 생성되었습니다\n", id);
Article article = new Article(id, title, body);
Connection conn = null;
PreparedStatement pstmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/JDBCTest?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Seoul&useOldAliasMetadataBehavior=true&zeroDateTimeNehavior=convertToNull";
conn = DriverManager.getConnection(url, "root", "");
System.out.println("연결 성공!");
String sql = "INSERT INTO article";
sql += " SET regDate = NOW()";
sql += ", updateDate = NOW()";
sql += ", title = '" + title + "'";
sql += ", `body` = '" + body + "';";
System.out.println(sql);
pstmt = conn.prepareStatement(sql);
int affectedRows = pstmt.executeUpdate();
System.out.println(affectedRows + "열에 적용됨");
} catch (ClassNotFoundException e) {
System.out.println("드라이버 로딩 실패");
} catch (SQLException e) {
System.out.println("에러: " + e);
} finally {
try {
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (pstmt != null && !pstmt.isClosed()) {
pstmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
lastArticleId++;
} else if (cmd.startsWith("article modify ")) {
int id = Integer.parseInt(cmd.split(" ")[2]);
System.out.printf("== %d번 게시물 수정 ==\n", id);
System.out.printf("새 제목 : ");
String title = sc.nextLine();
System.out.printf("새 내용 : ");
String body = sc.nextLine();
Connection conn = null;
PreparedStatement pstmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/JDBCTest?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Seoul&useOldAliasMetadataBehavior=true&zeroDateTimeNehavior=convertToNull";
conn = DriverManager.getConnection(url, "root", "");
System.out.println("연결 성공!");
String sql = "UPDATE article";
sql += " SET updateDate = NOW()";
sql += ", title = '" + title + "'";
sql += ", `body` = '" + body + "'";
sql += " WHERE id = " + id + ";";
System.out.println(sql);
pstmt = conn.prepareStatement(sql);
int affectedRows = pstmt.executeUpdate();
System.out.println(affectedRows + "열에 적용됨");
} catch (ClassNotFoundException e) {
System.out.println("드라이버 로딩 실패");
} catch (SQLException e) {
System.out.println("에러: " + e);
} finally {
try {
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (pstmt != null && !pstmt.isClosed()) {
pstmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
System.out.printf("%d번 게시물이 수정 되었습니다.\n", id);
} else if (cmd.startsWith("article delete ")) {
int id = Integer.parseInt(cmd.split(" ")[2]);
Connection conn = null;
PreparedStatement pstmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/JDBCTest?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Seoul&useOldAliasMetadataBehavior=true&zeroDateTimeNehavior=convertToNull";
conn = DriverManager.getConnection(url, "root", "");
System.out.println("연결 성공!");
SecSql sql = new SecSql();
sql.append("SELECT COUNT(*)");
sql.append("FROM article");
sql.append("WHERE id = ?", id);
int articlesCount = DBUtil.selectRowIntValue(conn, sql);
if (articlesCount == 0) {
System.out.printf("%d번 게시글은 존재하지 않습니다.\n", id);
continue;
}
System.out.printf("== %d번 게시물 삭제 ==\n", id);
sql = new SecSql();
sql.append("DELETE FROM article");
sql.append("WHERE id = ?", id);
DBUtil.delete(conn, sql);
System.out.printf("%d번 게시물이 삭제 되었습니다\n", id);
} catch (ClassNotFoundException e) {
System.out.println("드라이버 로딩 실패");
} catch (SQLException e) {
System.out.println("에러: " + e);
} finally {
try {
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (pstmt != null && !pstmt.isClosed()) {
pstmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
} else if (cmd.equals("article list")) {
System.out.println("== 게시물 리스트 ==");
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Article> articles = new ArrayList<>();
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/JDBCTest?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Seoul&useOldAliasMetadataBehavior=true&zeroDateTimeNehavior=convertToNull";
conn = DriverManager.getConnection(url, "root", "");
System.out.println("연결 성공!");
String sql = "SELECT *";
sql += " FROM article";
sql += " ORDER BY id DESC";
System.out.println(sql);
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while (rs.next()) {
int id = rs.getInt("id");
String regDate = rs.getString("regDate");
String updateDate = rs.getString("updateDate");
String title = rs.getString("title");
String body = rs.getString("body");
Article article = new Article(id, regDate, updateDate, title, body);
articles.add(article);
}
} catch (ClassNotFoundException e) {
System.out.println("드라이버 로딩 실패");
} catch (SQLException e) {
System.out.println("에러: " + e);
} finally {
try {
if (rs != null && !rs.isClosed()) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (pstmt != null && !pstmt.isClosed()) {
pstmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
if (articles.size() == 0) {
System.out.println("게시물이 없습니다");
continue;
}
System.out.println("번호 | 제목");
for (int i = 0; i < articles.size(); i++) {
Article article = articles.get(i);
System.out.printf("%4d | %s\n", article.id, article.title);
}
}
}
}
}
2. 실행
- 테이블이 다음과 같이 있다고 가정
- article delete 2를 입력하여 2번째 행을 제거
- 확인 (2번째 행이 제거됨)
'Back-End Study > DBMS' 카테고리의 다른 글
JDBC - 11. 회원가입 만들기 (0) | 2022.09.08 |
---|---|
JDBC - 10. DBUtil과 SecSql을 이용하여 Main의 방식 수정 (0) | 2022.09.07 |
JDBC - 8. 게시물 수정기능 구현 (0) | 2022.09.07 |
JDBC - 7. article list 시, 데이터를 DB로부터 가져오기 (0) | 2022.09.06 |
JDBC - 6. JDBC SELECT 테스트 (0) | 2022.09.06 |