DAO, SRP

이소연's avatar
Aug 05, 2024
DAO, SRP
DAO-Data Access Object => so, 재사용 가능 srp - 단일책임의 원칙 ~레이어를 나눔. 층마다 책임을 부여하는 것.
단일 책임 원칙
~레이어를 나눔. 층마다 책임을 부여
 
app / os / hw 각각 책임이 있고 책임을 나눔.
dao
notion image
💡
중요~외우삼. db는 다른 시스템. java/c언어 사용? 바이트/테이블 형태 데이터가 옴.. javaobject로 파싱을 해야 함. 그래야 편함. 자기 언어로 바꿔야 함!!! …하면 못다룬다고? int는 파싱할 필요 x
notion image
 
원래,
main >> db이런 방식(노란색)이었는데
dao가 생기면서 아래와 같은 방식(초록색)으로 됨.
notion image
main에서 영향 받은 행 int값을 insert를 하면 dao에서 select로 db에 가서 요청받은 영향받은 행이 온다.?
select는 dao에서 메인으로 table로 응답을 한다.
notion image
notion image
 
dao
-데이터 접근 방법 (select/ insert/ delete/ update)
 
notion image
 
java >>url >>공공데이터
공공데이터는 항상 json로 언어를 중간 언어로 바꾸어 보냄.
java는 java object(→ class)로 바꿔서 읽음??
 
테이블이랑 똑같이 생긴 class? 만들어야 한다고?(model에 만들어 본다고.?)
 
 
박스 3개 그림
table int가 db에서 dao로 옮.
뭐가 오든 다 string이 옴.
“” 항상 이게 옴?
 
String sql = "insert into account_tb(password,balance,created_at) values(?,? now())";
자바서버 한국 /데이터서버 미국에 있으면.. now하면 미국 시간으로 됨.
그래서 자바코드로 localdata로 하면 자바서버에서 한국에서 실행되서 한국시간으로 됨.
 
 
test방식이 여러 개가 있는데
본코드에서~
본코드 작성 > 그게 잘 되었는지 test에서 실행
tdd (난 중 배움.)
 
printstack 맨 위에 ~연쇄되어서/내가 만든 거 찾기.
디버깅 할 때 이걸로 하기. /개발에서는 이걸 보는게 맞음 . 원인 파악이 꾸ㅡㅌ나면 getmessage로 하면 됨.
 
ctrl + l : 정렬
구현체 impl?
 
bankdao
옛날코드 + table 보고 적음
 
db projection
: 컬럼을 골라내는 것.
 
커서내리는 것 중요. 외우삼
package dao; //DAO-Data Access Object //srp - 단일책임의 원칙 import db.DBConnection; import model.Account; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; 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(); return num; } catch (Exception 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(); boolean isRow = rs.next(); // 커서 한 칸 내리기 if(isRow){ 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(); // 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 void selectAll(){ } }
TOSTRING ROMBOL0V
벡터 : (동일타입 )연속적인 데이터
한 개 스칼라
 
숫자 1~10 벡터
1은 스칼라
 
가로 세로 있으면 매트릭스
 
package dao; //DAO-Data Access Object //srp - 단일책임의 원칙 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; 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(); return num; } catch (Exception 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; } }catch (Exception e){ e.printStackTrace(); } return null; } public List<Account> selectAll(){ Connection conn = DBConnection.getInstance(); // 꼭 있기 //java >> db bytestream 생김 try { String sql = "select * from account_tb order by number desc"; PreparedStatement pstmt = conn.prepareStatement(sql); //쿼리sql을 버퍼에 담음(""꺼) ResultSet rs = pstmt.executeQuery(); //sql flush(exe)하고 db가 응답해줌. / 그래서 br에 table이 옴. List<Account> accountList = new ArrayList<>(); // 스택 이야기 account 없어진다고? 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; } }
추상화_그림그리기(코드로 보면 안돼)
notion image
 
 
클래스(다른 타입) > collection(연속) >
하나씩 하면 안되니까 하나 model account만듦
>false나오면 종료. account list 반환되니까 분홍색을 줌.
 
lombok 다운
  1. 이건 유명하니까 lombok > download해도 됨. 혹은 방법 2
notion image
혹은 아래 코드 복사하여 intellij 코끼리 넣는 부분에 넣기
notion image
lombok 다운
  1. MVN REPOSITORY
-같은 게 많으면 이런 식으로 usages가 많은 거 사용하면 됨.
notion image
 
아래와 같이 있어도 디폴트 생성자 있는 것임 아무것도 안 만들었으니 기본으로 만들어짐.
notion image
 
notion image
crud : 이거 함.
create - insert
read -select
update
delete
 
 
number = x-1하면 안 됨. 이런 식으로 파라미트가 있어야 재사용 가능-v
notion image
 
notion image
try catch가 더 편함. 근데 return값이 -1,0,1인 경우도 알아야 해서 지금 이렇게 씀
notion image
 
여기서 set balance = balance +1000 이런 식으로 안 적는다.
이유는 증/감 모두 해야 되서 ‘?’로 함.
notion image
여러가지 테스트 방식이 있지만 우리는 이런 테스트 방식 씀
(given/when/then)
notion image
notion image
notion image
rs가 통으로 가지고 있음 rs- (git의 header처럼)커서를 들고 있음. 그 커서가 처음에는 coloumn (number줄)을 가르키고 있음
notion image
so,우리는 자료를 가져올 때 커서를 한 칸 밑으로 내려야 됨. 커서를 내리면서 읽어야 함.
notion image
projectiuon 4번(number, pw,balance, created_at 해서 총 4번)
 
 
 
notion image
notion image
result set하는 순간 또 정렬 >> 커서 내리고 projection 같은 거 -> so class에 담아야 함.
모든 계좌조회의 경우 arraylist 가능은 함.
 
이렇게 만들면 오류 뜸. 왜냐면 생성자가 없어서
notion image
💡
모든 파라미터의 생성자 만들어 주는 것.
so, 우리가 하나하나 하지 않아도 됨. lombok이 알아서 해줌.
notion image
 
notion image
즉, 이 경우 생성자를 하면 됨. 오류 사라짐.
notion image
(초기화시킬 때에는) 생성자 만들어서 하는 게 편함
setter도 가능하지만 동료가 싫어할 것임.
setter는 정보를 변경할 때하는 것. ex) balance값을 변경한다든지.
notion image
HELLO로 할지 account1로 만들지 어떻게 알아?(변수, 클래스 명이 다를 수 있으니까 resultset 로 함) 그래서 resutset rs = pstmt.executeQuery();식으로 함.
 
notion image
result 해서 하면 또 ~해야 되서 이걸로(account로-v)
 
notion image
 
부모라서. DIP 추상적인 것에 의존
notion image
내림차순해 줘야 (10~1 이런 순) 기본-오름차순
so, 전체조회는 거꾸로 (최근부터 해야 함.)
댓글 2000개 , insta -order by 최근 순. (descending) 아니면 나의 글 못 찾음. (왜냐하면 제일 오래된 글이 제일 위에 떠 있을 테니까)
 
 
notion image
이렇게 되면 박스를 계속 담고 버리고 다시 박스 만들고 버리고 의미 없어서 collection에 담아야 하미.
그리고 Account account를 while 문 앞에 배치. (박스 계속 만들 필요 없으니까)
 
여기서 자바부분을 좀 더 자세히 보면,
notion image
메인에서 키보드를 가지고 메인에서 요청 받으면 controler를 만들어줌 그것이 dao 호출 그것은 db호출 하나하나는 레이어라고 함.
keyboard(요청-v)→ main(실행시키는 것) > controller(클라이언트의 요청을 받는 애. (요청을 분기시키는 아이), 그 요청을 받아서 dao에 필요한 메서드를 호출하는 애. ) > dao (database와 상호작용하는 거.책임 안에 5개의 매서드 가지고 있음. ssidu)> db
 
 
자원명 대신 (파일명이 아니라) 식별자를 넣음.
 
op.gg?
//http://bank.com/account ~ 이렇게 주소만 적으면 생성/조회인지 몰라. 그래서 http매서드가 필요. 그게 get
전체계좌 주삼.
 
POST 줄게?-V
POST : DB에 INSERT
 
/10 : PK이다.식별자. 응답바디로 줌. REPONSE BODY
헤더에 마인타입이 필요. 어떤 데이터다 알려줘야 함.
 
POST INSERT 하려면 자바 CLIENT에 요청. 보안때문에.
자원을 요청X, 식별자 요청받아 DB에서 자료 받음?
URL~요청기법
DB의 데이터를 가져옴.
 
A.HTML??———————————————————————
//http://bank.com/account GET //http://bank.com/account/10 GET //http://bank.com/account POST //http://bank.com/account/1 DELETE //http://bank.com/account/1 PUT // /account // /account/1 // /account // /account/1 // /account/1
GET 요청 할 때는 바디가 없고 응답할 때는 있음’
DELETE는 줘야 할 거 없어.
 
HTTP에 바디가 없다
 
 
POST 요청바디O, 응답할 때는 없음
PUT 응답할 때(상태만 보내면 됨.)
notion image
notion image
notion image
notion image
외워 중요해
WRITE요청(db에 변경)은 돌려줄 게 없어 응답의 BODY가 필요X OKAY만 주면 됨.
READ(db에 변경x)
 
식별자만 받고 일하는 애를 뽑자고??
 
10001234 보내면 몰라
그래서 마인타입, 파싱이 중요
 
그래서 1000:1234야 둘이서 약속하면 둘이서만 쓸 수 ok 이거 안돼.
전 세계 사람들이랑 모두 하고 싶어→ mine타입, 전세계적 표준.
 
x-www.for.url.incoding-v
 
그래서 우리 이렇게 보낼거야.
 
password=1234&balance=1000
password=1234&balance=1000 // 0번지 password=1234 1번지 balance=1000-v 아님 반대?
import dao.BankDAO; import db.DBConnection; import model.Account; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; import java.util.Scanner; public class BankApp { public static void main(String[] args) { Scanner sc = new Scanner(System.in); //http://bank.com/account GET //http://bank.com/account/10 GET //http://bank.com/account POST //http://bank.com/account/1 DELETE //http://bank.com/account/1 PUT String method = sc.nextLine(); String action = sc.nextLine(); System.out.println("식별자를 입력하세요"); String action = sc.nextLine(); String body = ""; //라우팅 BankDAO bankDAO = new BankDAO(); if (method.equals("GET")){ if (action.equals("/account")){ List<Account> accountList = bankDAO.selectAll(); System.out.println(accountList); } else if (action.equals("/account/1")) { Account account = bankDAO.selectByNumber(1); System.out.println(account); } } else if (method.equals("POST")) { System.out.println("body 데이터를 입력하세요"); body = sc.nextLine(); // password=1234&balance=1000 // 0번지 password=1234 1번지 balance=1000-v 아님 반대? String[] st1 = body.split("&"); String password = st1[0].split("=")[1]; int balance = Integer.parseInt(st1[1].split("=")[1]); if(action.equals("/account")){ bankDAO.insert("",1000); } } else if (method.equals("PUT")) { } else if (method.equals("DELETE")) { } } }
www.naver.com?password~~이런 식으로 웹에서 씀
날씨 검색해보면 url창에서 볼 수 있어요
 
이거 라우터얌. 컨트롤러~~ 이거 아직 안했다
 
Share article

Coding's note