![movie](https://img.youtube.com/vi/kJexMyaeHDs/0.jpg)
영속성 컨텍스트
: 메모리 저장소, 엔티티 타입과 식별자를 키로 사용하는 캐시
- Entity Manger로 DB와 영속성 컨텍스트 사이에서 데이터 관리
Q1. 왜 두 entity가 다를까?
![](https://velog.velcdn.com/images/y39scode/post/3c9080c5-6d10-47b0-9e1c-a8c720486267/image.png)
- 상황: 하나씩 테스트를 했을 때는 문제가 없었지만, 통합테스트를 통과하지 못했음
![](https://velog.velcdn.com/images/y39scode/post/ccb502f4-1033-4025-93df-f4279f2d33b1/image.png)
영속성 컨텍스트 관리 상태
-
비영속(New)
: 영속성 컨텍스트로 관리가 안 됨
-
영속(Managed)
: 영속성 컨텍스트에게 관리됨
- DB와 동기화되고 트랜잭션 커밋시에 변경 사항이 지속
-
삭제(removed)
: 영속성 컨텍스트와의 연결이 끊기고,변경 사항 지속X
-
준영속(Detached)
: 예전에는 영속성 컨텍스트로 관리 되었지만 지금은 아님
- 유효한 entity지만 트랜잭션이 커밋될때 변경사항 지속되지 않음
save() 분기처리
![](https://velog.velcdn.com/images/y39scode/post/0d4fa40d-bdc3-4cf3-9603-ddba00742336/image.png)
준영속 entity와 영속으로 바뀐 entity는 다르다.
- 다시 영속이 될 때, id가 바뀌기 때문에 다른 entity로 인식
결론
- savaAndCompare() 때에는 비영속성-> 영속성
- id: null 이기 때문에 바로 DB에 저장이 됨
- DB에 저장된 entity와 PEPPER은 같음
- find() 때에는 준영속성 -> 영속성
- 앞의 테스트에서 저장되었기 때문에 id: 1
- 준영속성 -> 영속성이 되면서 id가 변경
- id가 달라졌기 때문에 PEPPER과 다른 entity로 인식함
Q2.삭제를 했는데 왜 조회가 되나?
![](https://velog.velcdn.com/images/y39scode/post/32f8ceed-85f3-4eb8-85be-a4682ec5bcd2/image.png)
- 상황: 삭제 -> 조회를 했는데 테스트가 통과함.
- 이상한 점: select 쿼리를 JPA가 날리지 않음
![](https://velog.velcdn.com/images/y39scode/post/69b40580-7bec-4fae-95d4-71beccd6907b/image.png)
원인
- 삭제는 했지만, 영속성 컨텍스트 안에 남아있기 때문에
추가
- findById()를 통해서 entity를 가져와 달라고 하는 건 실패함
- DB에 없기 때문에 가져올 수는 없음.
Q3. 삭제를 했는데 왜 삽입이 안 되나?
![](https://velog.velcdn.com/images/y39scode/post/a9447750-d9e1-4a40-9c07-5fc173b9ee8e/image.png)
- 실패 이유: unique에 위반되기 때문에 실행 불가
1차 캐시와 쓰기 지연
![](https://velog.velcdn.com/images/y39scode/post/73bf1b92-1d41-4f49-90ac-9d45512f54ac/image.png)
- id가 없는 경우(New, 비영속성)
- DB에 먼저 저장후 id를 넣어줌
- 그후 1차 캐시에 저장
![](https://velog.velcdn.com/images/y39scode/post/501a6720-f157-45c7-a511-4bbb7749b968/image.png)
- id가 있는 경우
- 1차 캐시에 먼저 저장
- 쓰기 지연 SQL 저장소
- 한번에 flush()를 통해서 DB에 반영
delete All
- 먼저 findAll을 통해서 entity를 가져옴
- 그 후에 for문을 통해서 delete를 실행
flush() 실행 조건
- 강제로 flush() 실행
- JPQL 쿼리를 실행
- 트랜잭션이 커밋
문제의 원인
![](https://velog.velcdn.com/images/y39scode/post/6fcf614f-0ac3-49a9-b2e8-e822c81db8fe/image.png)
- delete 문이 아직 쓰기 지연 저장소에 있음
- saveAll()의 entity들은 id가 없음
- 그래서 바로 DB에 저장을 시키려고함
즉, DB에 있는 entity를 다시 저장하는 꼴
해결법
- flush() 사용
- delete를 JPQL로 실행
- transact commit을 함
Q4. 수정을 했는데 왜 그대로지?
![](https://velog.velcdn.com/images/y39scode/post/4b96e0d5-6cd5-4ed4-8f41-af7b8ace1e46/image.png)
![](https://velog.velcdn.com/images/y39scode/post/aa2f1f4d-6571-4fe2-b37c-20c20e6d9d7a/image.png)
- 상황: save()를 했는데도 값이 변경되지 않았음
스냅샷
![](https://velog.velcdn.com/images/y39scode/post/f4bea00d-77bb-457f-8edf-a93c631a3429/image.png)
- 엔티티가 변경이 되었는지 비교를 위한 대조군으로 스냅샷 이용
언제나 JPQL은 flush를 날릴까?
- 아니다.
- JPQL이 특정 컬럼에 대한 것이라면, 그 컬럼에 대한 flush만 날림
결론
- JPQL이 적용되지 않는 이유
- age와 관련된 쿼리가 기존에 없어서 flush되는 것은 없음
- 또한 JPQL이 실행된다고 하더라도 자동으로 JPQL의 변경 내용이 flush 되는 건 아님.
해결법
- repository에 @Modifying(clearAutomatically = true) 사용
Q4. team이 왜 null인가?
![](https://velog.velcdn.com/images/y39scode/post/c474daaf-ad94-4459-a569-3dbc75b585f9/image.png)
![](https://velog.velcdn.com/images/y39scode/post/e8532486-126c-491c-a8e9-66b4ced333c7/image.png)
- 상황: 팀을 넣어준 상태인데 sort가 되지 않는 이유는?
fetch = FetchType.LAZY
![](https://velog.velcdn.com/images/y39scode/post/72ef91d6-e1f6-436b-b9d1-ac1af8805ccf/image.png)
- Proxy 객체: 가짜 객체, 실제 entity를 꺼낼때 채우겠다는 의미
![](https://velog.velcdn.com/images/y39scode/post/f4b7cb0f-cadc-4f78-a15b-dcccd6098a13/image.png)
해결방법
- compare을 필드를 직접 가져오지 않고 getTitle로 가져옴