![[Java] 24. JDBC (3) - 상품 프로그램 만들기](https://image.inblog.dev?url=https%3A%2F%2Finblog.ai%2Fapi%2Fog%3Ftitle%3D%255BJava%255D%252024.%2520JDBC%2520%283%29%2520-%2520%25EC%2583%2581%25ED%2592%2588%2520%25ED%2594%2584%25EB%25A1%259C%25EA%25B7%25B8%25EB%259E%25A8%2520%25EB%25A7%258C%25EB%2593%25A4%25EA%25B8%25B0%26logoUrl%3Dhttps%253A%252F%252Finblog.ai%252Finblog_logo.png%26blogTitle%3Djay0628&w=3840&q=75)
0. 패키지 구조

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