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