<복습>
Spring Data JPA Dependency 추가
: 포함된 dependency -JDBC, JPA, hibernate(jpa 구현체), AOP
왜 포함되어있을까? aop를 왜 포함하고 있을까?
- GlobalException처리->@RestControllerAdvice - AOP연결
- @Transactional-> 트랜잭션이 시작/끝을 알리기위해 앞뒤로 붙어야 함 스프링이 어노테이션을 달아놓으면 자동으로 해줌.
- DI, IOC, AOP 스프링만 가지고 있는 것이아니라, 좋은 걸 골라다가 만들어 놓은 프레임워크
왜 aop가 필요할까?
AOP (Aspect Oriented programming: 관점지향 프로그래밍)
-
관점 지향 프로그래밍
1) 구매 개발자: 구매 버튼 클릭 > ✔️ ~> 구매 완료
2) 장바구니 개발자: 장바구니 버튼 클릭 > ✔️ ~> 아이템 삭제 완료
3) 찜하기: 장바구니 버튼 클릭 > ✔️ ~> 찜하기 로직
4) 로그인 체크 개발자: 로그인 체크✔️
각각 다들 개발하려는 관심은 다르지만, 구매를 클릭했을 때 로그인이 여부를 체크하는 로직은 동일함.
=> 세로 관점을 봤을 때, 로그인 체크로직이 공통적임 새로운 관점으로 개발할게~! 필요할때 갖다 쓰기만 하면 됑!
@Before: 시점을 찍어놓는 것: 객체를 불러다가 메소드를 호출시켜줌
AOP란?
어떠한 메소드 코드를 실행시키전/후의 시점에서 다양한 로직들을 횡단적(세로 관점)으로 보았을 때 반복적인 로직 로직을 하나의 모듈로써 통합하여 짜는 프로그래밍
객체지향과 관점지향의 차이
- 객체 지향 프로그래밍: 잘 분리가 되어있고, 모듈화가 잘 되어있다는 뜻 필요한 시점에 객체.메소드를 호출 가능
- 하지만, 코드 중복이 일어날 수 밖에 없고, aop(관점 지향)을 적용하기 좋은 바탕이라고 생각
- 객체지향 프로그래밍은 응집도가 높고, 의존성이 낮고, 결합도가 낮고, 모듈화가 잘 되어있기 때문!
JPA(PI)<복습>
- JPA의 일꾼: EntityManager
- @Entity (cf. @Component -> ApplicationContext)
- persist(): entityContext에 추가, DB에 저장까지 해줘! = 영속화한다
entityContext: 영속화된 객체가 모여있는 공간
- @Transactional
- @Id: entityContext안에 너같은 애가 여러개 있어 식별할 수 있게 id를 부여하는 역할
EntityManager
persist(객체)
find(타입, 식별자)
cf. Spring도 type으로 빈 구별했지.. 하지만 여기에서는 객체가 여러개이기 때문에 식별자도 필요
= 같은 타입의 객체가 1개 뿐(default)="싱글톤 패턴"

데이터베이스에 데이터를 저장하기 위해서 EntityContext를 무조건 들려서 옴 -> "class 타입"와 "id"가 필요하기 때문
왜 식별자까지 필요할까? 똑같은 객체가 여러개 존재하기 때문에 각 객체를 식별하기 위해 @Id을 통해 식별이 가능함!
EntityManager-2
createQuery(쿼리):
cf. JPA는 자바-디비 패러다임 일치 목적!
=> 자바는 자바스럽게, 디비는 디비스럽게
- JPQL(Java Persistence Query Language)
자바스럽게 쿼리 짜면=> JPA가 알아서 SQL로 바꿔서 쓸게!
(like 슈도 코드)
- ex.
SQL: SELECT *(컬럼) FROM room(테이블 명);
JPQL: SELECT r.price(필드) FROM Room(클래스명) AS r(별칭)
clear(): 영속성 컨텍스트를 클리어! 다 비워버리는 것!
flush(): 영속성 컨텍스트 - DB 동기화
close():영속성 컨텍스트를 영업 종료!
DTO관련 구현 질문?
- 왜쓰는가? -> 어떻게 쓰는가?
- DTO는 몇 개가 적당할까??
- DTO 1개 vs 여러개: 2개 이상 만들기!
- 사용자의 요청마다 다른 request->dto->response
entity당 DTO 몇개씩 가지게 됨
- DTO <-> Entity 변환 어떤 계층?
- Controller: DTO(클라이언트 필요)
- Service: 변환하는 것도 로직이라고 생각
- Repository: Service에서 연산 다했을 것이라고 믿고, repository에서 변환
- 변환 방법: 필드, setter < 생성자, builder
- Entity는 객체(행위)라기 보단 개체
: Data덩어리(행위x)
- Entity는 지켜줘야징
1차 코드 작성
RoomService

분리가 잘 된것인가? NO
이유: 생성자 인자값이 바뀌거나 메소드명이 바뀐다면 다 같이 바꿔야함
그리고, 방을 저장하는 거지 방을 생성하는 건 아닌데 그 코드까지 있어야 하는가?에 대한 의문증,,,즉, service가 할일이 너무 많음!=>DTO로 코드 이동하자
JPA vs Spring Data JPA
- EntityManager를 누가 다루는가
-
JPA: 개발자가 직접
-
Spring Data JPA: Spring
+추상화(인터페이스 제공): 쉽고, 편하게 JPA 사용할 수 있음!
대왕 인터페이스 "JPARepository"
(1) (List)CrudRepository
(2) (List)PagingAndSortingRepository
(3) QueryByExampleExecutor
그럼 JPA->SpringJPA코드로 변환해보자!
- 가정: MAP->JPA->Spring Data JPA를 나중엔 쓸거야

변환을 하려고 했더니....
개방 폐쇄 원칙을 위반!!!⛔️
-> 해결책: interface/추상클래스 🌟추상화🌟


- Repository가 바꾸어도 서비스가 바뀌지 않도록 하기 위해 ! 중간에 인터페이스를 둠
사실 자바세상에서 확장은 추상화말고는 답이 없어요,,
어렵조..?
다시다시 쉬운 예제로 한번 더 갈게용!
아니 그거 기억나시나요 폰 사람 예제요...
그게 무려 여기서 쓰일려고 미리 했던 거였던 거였던 거였다요...
대박!!!!!!!!!!!이런 큰그림을

여기서 잠깐,, 테스트 코드를 짜려고 했는데..
test코드가 aop가 있었다고..?
aop가 test에 나와?!!?

예전의 기억을 살려 아래 코드에 먼저 적용해보쟈~

service변경없이 A, B모두 사용가능
(위세줄은 spring이 대신 해줌)하하 개편해!

아니 근데 안되자나왜 안넣어주냐고!!!!
nullpointerException이 터져!개빡쳐!
Test코드에서는 스프링이 일을 안하는 거구낭...
스프링 더 일하자,,
해결방안 : 클래스 위에 @SpringBootTest 추가하면 됨
그럼 스프링이 테스트에서도 일을하게 됩니당! 스프링 열일해!
음 이제 기동은 되는데 여전히 NullPointerException이 뜨네!??!
어떻게 해결해야 할까?!
