[Java] 24. JDBC (3) - 상품 프로그램 만들기

김주희's avatar
Apr 21, 2025
[Java] 24. JDBC (3) - 상품 프로그램 만들기

0. 패키지 구조

notion image

1. build.gradle

dependencies { implementation group: 'com.mysql', name: 'mysql-connector-j', version: '8.0.33' testImplementation platform('org.junit:junit-bom:5.10.0') testImplementation 'org.junit.jupiter:junit-jupiter' }
 

2. DBConnection

import java.sql.Connection; import java.sql.DriverManager; public class DBConnection { // 다른 db 만들고 싶으면 매개변수로 url,username,password 받으면 됨 public static Connection getConnection() { String url = "jdbc:mysql://localhost:3306/store"; String username = "root"; String password = "bitc5600!"; try { Class.forName("com.mysql.cj.jdbc.Driver"); // conn = 프로토콜이 적용된 소켓 Connection conn = DriverManager.getConnection(url, username, password); return conn; } catch (Exception e) { throw new RuntimeException(e); } } }
 

3. Store

package model; // 테이블의 스키마(컬럼)을 보고 만듦 // model -> DB에 있는 table 데이터를 비슷하게 구현한 것 public class Store { // 컬럼과 이름 동일하게 만드는게 좋음 // 예외) db - hello_price <-> java - helloPrice // null은 참조자료형에만 넣을 수 있음 -> wrapper // join 등으로 조회된 데이터(가공된 데이터들)를 위한 모델도 만들어야 하지만 미리 만들 필요 없음 private Integer id; private String name; private Integer price; private Integer qty; // 개체 호출시 toString 자동 호출 @Override public String toString() { return "Store{" + "id=" + id + ", name='" + name + '\'' + ", price=" + price + ", qty=" + qty + '}'; } public Store(Integer id, String name, Integer price, Integer qty) { this.id = id; this.name = name; this.price = price; this.qty = qty; } public Integer getId() { return id; } public String getName() { return name; } public Integer getPrice() { return price; } public Integer getQty() { return qty; } }
 

4. StoreDAO

package dao; import model.Store; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; // Data(DB데이터 의미) Access Object // DB Connection과의 관계: is(X), has(O) -> DB Connection에 의존 public class StoreDAO { private Connection conn; public StoreDAO(Connection con) { this.conn = con; } // 1. 한 건 조회 // 클래스 리턴 but 모르겠으면 일단 void로 만들고 생각 public Store 한건조회(int id){ try { // 2. 버퍼 String sql = "select id, name, price, qty from store_tb where id = ?"; PreparedStatement psmt = conn.prepareStatement(sql); psmt.setInt(1, id); // 3. flush (rs = table 조회 결과 즉 view) ResultSet rs = psmt.executeQuery(); // data dictionary에서 sql문 먼저 확인 -> 여기서 터짐 boolean isThere = rs.next(); // 커서 한 칸 내리기 if (isThere){ // model(class)에 담아야 return Store model = new Store( rs.getInt("id"), rs.getString("name"), rs.getInt("price"), rs.getInt("qty") ); return model; // return 실행되면 메서드 종료 } // 여기는 error 떴을때 return 안됨 } catch (SQLException e) { throw new RuntimeException(e); } return null; // 여기는 무조건 실행되니까 return 위치 // null = 조회된 결과 없다는 뜻 } // 2. 전체 조회 // 전체 조회는 기본적으로 desc -> 그래야 ux가 좋아짐 // 전체 조회의 책임: 전체 조회해서 return public List<Store> 전체조회(){ List<Store> models = new ArrayList<>(); // Generic : new할때 type 결정 try{ String sql = "select * from store_tb order by id desc"; // 최신 상품이 위로 PreparedStatement psmt = conn.prepareStatement(sql); ResultSet rs = psmt.executeQuery(); while(rs.next()){ // db의 행의 개수를 알 수 없기 때문에 for(X) // cursor 여러개 => model도 여러개 //model 여러개, 벡터 -> 컬렉션, arrayList로 //여기는 while의 stack -> while 끝나면 날라감 ({} -> stack) But, list에 옮길거니까 날라가도 괜찮음 // cursor 한 칸 내려오고 projection한걸 새로운 객체 model로 만듦 Store model = new Store( rs.getInt("id"), rs.getString("name"), rs.getInt("price"), rs.getInt("qty") ); // 날라가기 전에 list에 담기 models.add(model); } return models; }catch (Exception e){ throw new RuntimeException(e); } } // 3. 한 건 추가 public void 한건추가(String name, int price, int qty){ // Store model로 받을 경우 id는 null로 하면 됨 try{ String sql = "insert into store_tb (name, price, qty) values(?, ?, ?)"; // 여기서 변수 바인딩 하면 복잡해짐 PreparedStatement psmt = conn.prepareStatement(sql); // 버퍼에는 물음표 채운 sql문이 들어감 psmt.setString(1, name); // 첫번째 물음표 psmt.setInt(2, price); psmt.setInt(3, qty); // 변경된 행의 개수 (변경된 게 없으면 0) int result = psmt.executeUpdate(); // write - insert, update, delete if (result == 0){ throw new RuntimeException("insert failed"); } }catch (Exception e){ throw new RuntimeException(e); } } // 4. 한 건 수정 public void 한건수정(String name, int price, int qty, int id){ try{ String sql = "update store_tb set name = ?, price = ?, qty = ? where id = ?"; PreparedStatement psmt = conn.prepareStatement(sql); psmt.setString(1, name); psmt.setInt(2, price); psmt.setInt(3, qty); psmt.setInt(4, id); int result = psmt.executeUpdate(); if (result == 0){ throw new RuntimeException("니가 준 번호가 없나봐ㅠ.ㅠ update failed"); } }catch (Exception e){ throw new RuntimeException(e); } } // 5. 한 건 삭제 public void 한건삭제(int id){ try{ String sql = "delete from store_tb where id = ?"; PreparedStatement psmt = conn.prepareStatement(sql); psmt.setInt(1, id); int result = psmt.executeUpdate(); if (result == 0){ throw new RuntimeException("니가 준 번호가 없나봐 ㅠ.ㅠ delete failed"); } }catch (Exception e){ throw new RuntimeException(e); } } }
 
 

5. StoreApp

import dao.StoreDAO; import model.Store; import java.sql.*; import java.util.List; public class StoreApp { public static void main(String[] args) { // 1. DB 연결 - 세션 만들어짐 Connection conn = DBConnection.getConnection(); // 의존성 주입 // 2. DAO 연결 StoreDAO dao = new StoreDAO(conn); // 3. 한건조회 /* Store model = dao.한건조회(3); System.out.println(model); */ // 4. 한건추가 //dao.한건추가("감자", 500, 2000); // 5. 한건수정 // 원래는 조회해서 내가 수정하고자 하는 것만 + 나머지는 getter로 가져오기 //dao.한건수정("감자", 500, 10000, 3); // 6. 한건삭제 //dao.한건삭제(1); // 7. 전체조회 List<Store> models = dao.전체조회(); for (Store model : models) { System.out.println(model); } } }
Share article

jay0628