
📝ORM(Object-Relational Mapping)
객체와 관계형 데이터베이스를 매핑하는 기술 또는 방식입니다.
📝JPA(Java Persistence API)
자바에서 ORM을 사용하기 위한 표준 명세(스펙)입니다.
📝엔티티 (Entity)
데이터베이스의 테이블과 1:1로 매핑되는 자바 클래스로 모델이라고 생각하면 편하다
📝영속성 컨텍스트

엔티티를 영구 저장하는 환경으로 JPA에 있는 persist라는 영속화시키는 함수를 사용했을 때 이게 실제로 바로 DB에 저장되는 게 아닌 영속성 컨텍스트라는 공간에 저장한 이후에 트랜잭션이 끝나서 Commit이 되었을 때 변경내용이 DB에 저장되게 됩니다.
📝엔티티 생명주기
비영속
- 영속성 컨텍스트와 전혀 관계 없는 새로운 상태 → persist 안 한 상태
영속
- 영속성 컨텍스트에 관리되는 상태 → persist 한 상태
준영속
- 영속성 컨텍스트에 저장되었다가 분리된 상태
삭제
- 영속성 컨텍스트에서 삭제된 상태
📝영속성 컨텍스트 특징
1차 캐시 조회
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
//1차에 캐시
em.persist(member);
//1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");
영속성 컨텍스트에서 먼저 저장되어있는 걸 조회하기 때문에 성능의 이점이 있다.
(트랜잭션 단위로 사용하기 때문에 캐시 내용이 남아있는게 아니라서 다른곳에서 조회하더라도 없기 때문에 DB에서 재조회해서 크게 이점이 되지 않는 경우가 많다.)
조회 과정
- 1차캐시에서 조회
- 없을 때 DB조회
- DB조회한 경우 1차캐시에 저장
- 반환
트랜잭션 쓰기 지연

트랜잭션 범위에서는 1차 캐시에 쌓아둔 이후에 transaction.commit()을 할 때 DB에 INSERT문이 날아가게 된다. (버퍼 기능을 이용한 속도 및 성능 이점)
변경 감지 (엔티티 수정) Dirty Check
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
// 영속 엔터티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔터티 수정
memberA.setUsername("hi");
memberA.setAge(10);
transaction.commit();
조회해온 엔터티를 setter로 수정만 해도 조회해온 실제 데이터도 커밋시 수정된다. (update문 필요 없음)
엔티티 삭제
// 삭제 조회 엔티티
Member memberA = em.find(Member.class, “memberA");
em.remove(memberA);
플러시 (flush)
영속성 컨텍스트 변경 내용을 DB에 반영하는 과정으로 트랜잭션이 걸려있는 경우 Commit단계를 해야 최종 반영이 된다.
flush를 해도 영속성컨텍스트에 있는 1차 캐시는 계속 존재한다.
플러시 동작 시키는 법
- em.flush() - 직접 호출
- 트랜잭션 커밋 - 플러시 자동 호출
- JPQL 쿼리 실행 - 플러시 자동 호출
굳이 중간에 flush를 해야하나?
- ID가 지금 당장 필요할 때
→ IDENTITIY같은 전략에서는 INSERT가 나가야 PK가 생기기 때문에 바로 확보하려는 목적 - 대량 UPSERT의 경우
→ flush로 SQL을 보내고 clear로 1차 캐시 비워 메모리가 터지는 걸 막습니다. - 변경사항이 이미 DB에 반영되어야 다음 쿼리가 진행 가능할 때
→ 동시성 문제 등
준영속 상태
JPA가 더이상 해당 엔티티를 관리하지 않아 변경감지, 1차캐시등을 이용할 수 없습니다.
준영속 상태 만들기
- em.detach()
→ 특정 엔터티만 준영속 상태로 변경 - em.clear()
→ 영속성 컨텍스트 모두 초기화 - em.close()
→ 영속성 컨텍스트 종료
🔗 참고 및 출처