Data Access Object - 데이터베이스와 상호작용하는 오브젝트
SRP - 단일 책임 원칙
위와 같이 사용하면 재사용은 불가능
재사용을 위해 dao 패키지를 만들어 BankDAO 클래스를 만들어준다.
DAO
코드
package dao;
import db.DBConnection;
import model.Account;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
/**
 * DAO - Data Access Object
 * SRP - 단일책임의 원칙
 */
public class BankDAO {
    public int deleteByNumber(int number){
        Connection conn = DBConnection.getInstance();
        try {
            String sql ="delete from account_tb where number = ?";
            PreparedStatement pstmt = conn.prepareStatement(sql); // 버퍼
            pstmt.setInt(1,number); // 쿼리 완성
            int num = pstmt.executeUpdate(); // flush
            return num;
        } catch (Exception e) {
//            throw new RuntimeException(e); // 호출자에게 위임
            e.printStackTrace();
        }
        return -1;
    }
    public int insert(String password, int balance){
        Connection conn = DBConnection.getInstance();
        try {
            String sql ="insert into account_tb(password, balance, created_at)" +
                    "values(?,?,now())";
            PreparedStatement pstmt = conn.prepareStatement(sql); // 버퍼
            pstmt.setString(1,password);
            pstmt.setInt(2,balance);
            int num = pstmt.executeUpdate();
            return num;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }
    public int updateByNumber(int balance, int number){
        Connection conn = DBConnection.getInstance();
        try {
            String sql ="update account_tb set balance = ? where number = ?";
            PreparedStatement pstmt = conn.prepareStatement(sql); // 버퍼
            pstmt.setInt(1,balance);
            pstmt.setInt(2,number);
            int num = pstmt.executeUpdate();
            return num;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }
    public Account selectByNumber(int number){
        Connection conn = DBConnection.getInstance();
        try {
            String sql = "select * from account_tb where number =?";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1,number);
            ResultSet rs = pstmt.executeQuery();
            if(rs.next()){ // 커서 한칸 내리기
                Account account = new Account(
                        rs.getInt("number"),
                        rs.getString("password"),
                        rs.getInt("balance"),
                        rs.getTimestamp("created_at")
                );
                return account;
            }
//            System.out.println(isRow);
//            System.out.println(rs.getInt("number"));
//            System.out.println(rs.getString("password"));
//            System.out.println(rs.getInt("balance"));
//            System.out.println(rs.getTimestamp("created_at"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public List<Account> selectAll(){
        Connection conn = DBConnection.getInstance();
        try {
            String sql = "select * from account_tb order by number desc";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            ResultSet rs = pstmt.executeQuery();
            List<Account> accountList = new ArrayList<>();
            while(rs.next()){
                Account account = new Account(
                        rs.getInt("number"),
                        rs.getString("password"),
                        rs.getInt("balance"),
                        rs.getTimestamp("created_at")
                );
                accountList.add(account);
            }
            return accountList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}Insert, Delete, Update 는 변경된 행의 갯수를 return한다. DAO는 main에 int로 return(따로 파싱이 필요없음)
select는 DB가 DAO에게 table을 return한다. DAO는 main에 자기언어(java object)로 바꿔서 return해줘야함.
Model
model - 테이블과 같은 구조의 Class를 만들어야함.
코드
package model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
import java.sql.Timestamp;
/**
 * DB에 select하기 위한 오브젝트
 */
@ToString
@AllArgsConstructor
@Getter
public class Account {
    private int number;
    private String password;
    private int balance;
    private Timestamp createdAt; // java.sql의 Timestamp, 카멜표기법 사용'
}BankApp main 코드 잘라내기
BankDAO에 작성
Test
given(파라미터)-when(본코드 실행)-then(검증)
코드
package dao;
import model.Account;
import org.junit.jupiter.api.Test;
import java.util.List;
public class BankDAOTest {
    @Test
    public void selectAll_test(){
        // given
        // when
        BankDAO dao = new BankDAO();
        List<Account> accountList = dao.selectAll();
        System.out.println(accountList.size());
        System.out.println(accountList);
    }
    @Test
    public void selectByNumber_test(){
        // given
        int number = 7;
        // when
        BankDAO dao = new BankDAO();
        Account account = dao.selectByNumber(number);
        // then
        if(account == null){
            System.out.println(number+"로 조회된 값이 없습니다.");
        }else{
            System.out.println(account);
//            System.out.println(account.getNumber());
//            System.out.println(account.getPassword());
//            System.out.println(account.getBalance());
//            System.out.println(account.getCreatedAt());
        }
    }
    @Test
    public void deleteByNumber_test(){
        // given = 파라미터
        int number = 4;
        // when = 본코드 실행
        BankDAO dao = new BankDAO();
        int result = dao.deleteByNumber(number);
        // then = 검증
        if(result == 1){
            System.out.println("삭제 성공");
        }else if(result == 0){
            System.out.println(number +"번호를 찾을 수 없습니다.");
        }else {
            System.out.println("삭제 실패");
        }
    }
    @Test
    public void insert_test(){
        // given
        String password = "1234";
        int balance = 630000;
        // when
        BankDAO dao = new BankDAO();
        int result = dao.insert(password, balance);
        // then
        if(result == 1){
            System.out.println("성공");
        }else{
            System.out.println("실패");
        }
    }
    @Test
    public void updateByNumber_test(){
        // given
        int balance = 0;
        int number = 3;
        // when
        BankDAO dao = new BankDAO();
        int result = dao.updateByNumber(balance,number);
        // then
        if(result == 1){
            System.out.println("업데이트 성공");
        }else if(result == 0){
            System.out.println(number+"번호를 찾을 수 없습니다.");
        }else{
            System.out.println("업데이트 실패");
        }
    }
}Main
데이터 파싱을 위해 MIME타입 - application/x-www-form-urlencoded
→ 그냥 이거만 쓴다 보면 됨 표준
코드
import dao.BankDAO;
import model.Account;
import java.sql.SQLOutput;
import java.util.List;
import java.util.Scanner;
public class BankApp {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 식별자 요청
        // GET, DELETE 는 HEAD만 있으면 됨(BODY가 없다), 쿼리 생성가능
        // http://bank.com/account GET -> select * from account_tb
        // http://bank.com/account/1 GET -> select * from account_tb where number = 1;
        // http://bank.com/account/1 DELETE -> delete from account_tb where number = 1;
        // PUT, POST는 BODY 데이터가 필요함.
        // http://bank.com/account/1 PUT
        // http://bank.com/account POST
        System.out.println("메서드를 입력하세요");
        String method = sc.nextLine();
        System.out.println("식별자를 입력하세요");
        String action = sc.nextLine();
        String body = "";
        BankDAO bankDAO = new BankDAO();
        if (method.equals("GET")){
            // 식별자 끝자리 숫자
            String[] st1 = action.split("/");
            int number = Integer.parseInt(st1[2]);
            if(action.equals("/account")){
                List<Account> accountList = bankDAO.selectAll();
                System.out.println(accountList);
            }else if(st1.length == 3 && st1[0].isEmpty() && st1[1].equals("account")){
                bankDAO.selectByNumber(number);
                Account account = bankDAO.selectByNumber(number);
                System.out.println(account);
            }
        } else if (method.equals("POST")) {
            System.out.println("body 데이터를 입력하세요");
            body = sc.nextLine();
            // password=1234&balance=1000
            String[] st1 = body.split("&");
            String password = st1[0].split("=")[1];
            int balance = Integer.parseInt(st1[1].split("=")[1]);
            if(action.equals("/account")){
                bankDAO.insert(password,balance);
            }
        } else if (method.equals("PUT")) {
            System.out.println("body 데이터를 입력하세요");
            body = sc.nextLine();
            // balance=1000&number=1
            String[] st1 = body.split("&");
            int balance = Integer.parseInt(st1[0].split("=")[1]);
            int number = Integer.parseInt(st1[1].split("=")[1]);
            if(action.equals("/account")){
                bankDAO.updateByNumber(balance,number);
            }
        } else if (method.equals("DELETE")){
            String[] st1 = action.split("/");
            int number = Integer.parseInt(st1[2]);
            if(st1.length == 3 && st1[0].isEmpty() && st1[1].equals("account")) {
                bankDAO.deleteByNumber(number);
            }
        }
    }
}Share article