https://docs.spring.io/spring-framework/reference/data-access/orm/hibernate.html
Import javax.persistence.*;
EntityManagerFactory emf = Persistence.createEntityManagerFactory("영속성 유닛 이름");
애플리케이션 전체에서 딱 한번만 생성
하고 공유해서 사용함.EntityManager em = emf.createEntityManager();
em.close();
emf.close();
사용을 마친 엔티티 매니저, 팩토리는 모두 종료해야함.
EntityTransaction tx = EntityManager.getTransaction();
try{
tx.begin();
logic(em);
tx.commit();
}catch (Exception e){
tx.rollback();
}
트랜젝션을 통한 커밋, 롤백을 통해 DB의 영속성 유지를 가능하게 함.
EntityManager.persist();
EntityManger.remove();
EntityManger.find(엔티티.class, 아이디)
em.find(Member.class, id)
https://www.javatpoint.com/spring-boot-jpa
- 엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전함, 서로 다른 스레드 간에 공유 가능
- 엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제가 발생하므로 스레드 간 공유 불가능
엔티티 매니저는 데이터 베이스 연결이 필요한 시점 전까지는 커넥션을 얻지 않음
- 보통 트랜젝션을 시작할때 커넥션을 얻음
엔티티 매니저를 통해 엔티티를 저장/조회 할 시 엔티티 매니저는 영속성 컨텍스트에 해당 엔티티를 보관하고 관리함.
엔티티 객체를 생성했을 때, 영속성 컨텍스트에 관련되지 않은 상태
엔티티 매니저를 통해서 엔티티를 영속성 컨텍스트에 저장햇을 때,
영속성 컨텍스트에 의해 관리되는 영속상태
EntityManager.persist()
영속성 컨텍스트가 관리하던 영속 상태 엔티티가 더이상 관리되지 않으면 준영속 상태
EntityManager.close()
,EntityManager.claer()
EntityManager.detach(엔티티 객체)
엔티티를 영속성 컨텍스트, DB에서 삭제한 상태
EntityManager.remove(엔티티 객체)
- 1차 캐시
- 동일성 보장
- 트랜잭션을 지원하는 쓰기 지연
- 변경 감지
- 지연 로딩
컨텍스트 내부 Map
식별자 값 : 엔티티 클래스의 Id를 Key로 식별한다.
Id를 가진 Key가 컨텍스트 내부 캐시에 존재하지 않으면 데이터베이스에 조회해서 데이터를 컨텍스트 내부에 유지한다.
영속성 컨텍스트 내부에 존재하는 인스턴스를 EntityManager.find() 를 통해 조회했을 때, 같은 Id로 두 번 참조하여 객체를 저장하면 두 인스턴스 객체는 동일하다. (==)
- 영속성 컨텍스트에 엔티티를 등록할 때, 바로 DB에 저장하지 않고
내부 쿼리 저장소
에 INSERT SQL을 쌓아둠.- 트랜젝션 커밋 시에 쌓아둔 쿼리를 데이터 베이스로 보냄.
Flush
- 트랜젝션 커밋 시 엔티티 매니저는 영속성 컨텍스트를 플러시함.
- : 영속성 컨텍스트 내부의 변경 내용과 DB를 동기화하여 데이터를 반영함.
영속 상태인 엔티티만(영속성 컨텍스트에 의해 관리되는) 변경감지 범위에 해당함
- 별도의 수정 메서드나 쿼리 없이, 엔티티를 조회하여 해당 엔티티의 필드 값을 변경해주면
- 엔티티 컨텍스트 내부에 처음 매핑 되었던 Key-Value와 함께있는 스냅샷과 해당 엔티티를 비교함.
- 여기서 변경된 점을 비교하여 수정 SQL을 DB에 반영해서 커밋
UPDATE 쿼리에 모든 필드를 반영함. -> UPDATE 문마다 차별화할 필요 없이 모든 필드를 다 쓰는 쿼리문을 반복해서 사용가능.
- 모든 필드를 UPDATE문에 포함시키지 않으려면
@DynamicUpdate
,@DynamicInsert
어노테이션을 사용
플러시 모드
- FlushModeType.AUTO: 커밋이나 쿼리를 실행할 때 플러시(default)
- FlushModeType.COMMIT: 커밋할 때만 플러시
EntityManager.setFlushMode(FlushModeType.COMMIT)
준영속 상태의 엔티티는 영속성 컨텍스트의 변경감지 범위에 들지 않는다.
EntityManager.detach(엔티티 객체)
-> 컨텍스트 내부 캐시 맵에서 해당 엔티티 매핑 정보를 제거- 해당 엔티티에 대한 SQL 문도 쓰기지연 SQL 저장소에서 사라짐.
지연 로딩 불가능 ( 프록시 객체를 영속성 컨텍스트를 통해 불러오는데, 영속성 컨텍스트에 의해 관리되지 않기 때문)
EntityManager.merge(엔티티 객체)
를 통해서 다시 영속성 컨텍스트에 관리받는 영속상태로 변경가능하다.
return 새로운 영속 상태의 엔티티(새로운 인스턴스)
병합도 EntityManager.persist(엔티티 객체)
처럼 캐시를 조회하고 엔티티 매핑 정보가 없으면 DB에서 조회하거나 새로운 엔티티를 만든다. (save or update)