일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 프로그래머스
- 싸피 기자단
- 자바 알고리즘
- 자바스크립트 자료구조
- 자바스크립트
- 인프런
- swea
- SSAFYcial
- 자료구조
- 싸피11기
- 싸피10기
- 리액트
- 코드트리
- jpa
- 알고리즘 자바
- 코딩테스트
- 비동기
- 프론트엔드
- 알고리즘
- ssafy
- 싸피 대전캠퍼스
- 자바 코딩테스트
- 싸피
- 코딩테스트 자바
- 싸피셜
- 싸피 10기
- 싸피 12기
- 개발자
- 싸피 11기
- 백준
- Today
- Total
병아리의 코딩 일기
[JPA] 영속성 컨텍스트의 이점 본문
저번 시간에는 영속성 컨텍스트란 무엇인지에 대해 알아보았다.
이번엔 '영속성 컨텍스트가 가진 이점'에 대해 알아보자!
1. 1차 캐시에서 조회한다.
Member member = new Member();
member.setId("member1");
member.setName("회원1");
//1차 캐시에 저장됨
em.persist(member);
//1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");
멤버 객체를 만들고 영속성 컨텍스트에 담으면 @Id : "membrer1"를 Key , Entity : Member 를 값으로 하는 1차 캐시가 생성된다.
그래서 findMember를 할 때 1차 캐시에서 조회한다. 즉, 실행해보면 select 쿼리가 따로 안나간다!
member findMember2 = em.find(Member.class, "member2");
여기서 만약 Member2를 찾고 싶으면 방금 시나리오에서 1차 캐시에 없었기 때문에 DB에서 조회한다.
Member findMember = em.find(Member.class, 101L);
Member findMember2 = em.find(Member.class, 101L);
이렇게 하면 쿼리가 한번만 나간다. 두번째 findMember2 는 1차 캐시에서 조회하기 때문이다. 비즈니스가 정말 복잡할 때는 도움이 될 수도 있다. 성능적인 이점보다는 컨셉을 이해할 때 주는 이점이 있다.
* 데이터 베이스 한 트랜젝션 안에서만 효과가 있기에 그렇게 큰 성능의 이점을 가지고 있진 않다.
System.out.println("result =" + (findMember == findMember2));
또한 JPA는 영속 엔티티의 동일성을 보장해준다.
결과 : result =true
2. 트랜잭션을 지원하는 쓰기지연
em.persist(memberA);
em.persist(memberB);
여기까진 INSERT SQL을 데이터베이스에 보내지않는다.
em.persist(memberA);
em.persist(memberB);
tx.commit();
트랜잭션을 커밋하는 순간 INSERT SQL을 데이터베이스에 보낸다.
영속성 컨텍스트에는 쓰기지연 SQL 저장소라는 재미난 것이 있다.
em.persist(member)를 하면 JPA가 엔티티를 분석을 해서 INSERT쿼리를 생성하고 쓰기 지연 SQL 저장소에 넣어두는 것이다.
A, B 둘다 쌓여있는 상태에서 transaction을 커밋하는 순간 flush가 되면서 날라가고 실제 DB 트렌젝션이 커밋된다.
Member member1 = new Member(150L, "A");
Member member2 = new Member(160L, "B");
em.persist(member1);
em.persist(member2);
System.out.println("===================");
tx.commit();
결과를 보면 "========"이후 tx.commit(); 이 실행된 시점에서 쿼리가 나가는 것을 볼 수 있다!
3. 엔티티 수정 (변경감지 - Dirty Checking)
Member member = em.find(Member.class, 150L);
member.setName("ZZZZZ");
이후에 따로 persist를 해줄 필요가 없다.
JPA 목적은 자바 컬렉션 다루듯이 객체를 다루는 것이다.
자바 컬렉션에서 값을 꺼내서 변경하면 그걸 다시 컬렉션에 집어넣는가? 아니다.
오히려 em.persist(member); 라는 코드를 쓰면 안된다.
실행 결과를 보면 마법 같이 자동으로 update 쿼리가 나간 것을 볼 수 있다.
이 비밀은 영속성 컨텍스트 안에 다 있다.
JPA는 tx.commit 시점에 내부적으로 flush() 라는 것이 호출된다.
이때 엔티티와 스냅샷을 비교하는데,
1차 캐시에는 Id, Entity, 스냅샷 이라는 것이 있다.
내가 값을 읽어온 그 최초 시점에 스냅샷으로 떠놓고 member의 값을 변경하면 commit되는 시점에 값을 비교해서 바뀌었으면 update쿼리를 쓰기 지연 SQL 저장소에 만들어놓고, 이걸 데이터베이스에 반영하고 커밋한다.
그러니까 이런식으로 코드를 짜면 안된다. em.update(member); 를 안 써도 이미 JPA에서는 update 쿼리가 날라간다.
Member member = em.find(Member.class, "memberA");
member.setName("ZZZZZ");
if(member.getName().equals("ZZZZZ")) {
em.update(member);
}
4. 엔티티 삭제
Member memberA = em.find(Member.class, "memberA");
em.remove(memberA);
엔티티를 찾아와서 remove 하면 삭제가 된다. 방금의 메커니즘과 똑같고 트랜젝션 커밋 시점에 delete 쿼리가 나간다.
여기까지 영속성 컨텍스트의 이점에 대해 알아보았다.
'자바 Java > Spring' 카테고리의 다른 글
[JPA]플러시 (0) | 2023.02.15 |
---|---|
[JPA] 영속성 컨텍스트란? (0) | 2023.02.15 |
JPA 구동 방식 (0) | 2023.02.15 |