목표
- JPA를 활용하기 위해 가장 중요한 개념인 영속성 컨텍스트의 기능 이해하기
- Entity의 생명 주기 이해하기
영속성 컨텍스트(Persistent Context)
영속성 컨텍스트란 엔티티를 관리하고 영속화시키는 환경을 의미합니다.
영속성 컨텍스트가 지원하는 기능은 다음과 같습니다.
- 지연로딩
- 동일성 보장
- 1차 캐시
- 변경 감지
- 트랜잭션을 지원하는 쓰기 지연
Entity Manager와 Entity Manager Factory
Entity Manager는 엔티티를 조회하거나 등록, 수정, 삭제 시키기 위해 DB에 접근할 수 있는 객체입니다.
EntityManagerFactory는 Entity Manager를 생성합니다. 객체 생성 비용이 상당히 크기 때문에 한번만 생성하여 애플리케이션 전체에서 사용합니다.
Entity 생명주기
1. 비영속(New) : 영속성 컨텍스트와 관계가 없는 상태
//비영속 엔티티 생성
Employee employee = new Employee();
employee.setName("kim");
2. 영속(Managed) : 영속성 컨텍스트에 저장된 상태
저장하거나 조회할 경우 해당 엔티티는 Persistence Context의 1차 캐시에 저장되어 영속화된다.
@Autowired
private EmployeeDao employeeDao; // JpaRepository를 상속받음
public void save(Employee employee){
employeeDao.save(employee); //employee 객체 영속화
}
public Employee findById(Integer id){
return employeeDao.findById(id).orElse(null); // employee 객체 영속화
}
3. 준영속(Detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
//준영속 상태를 만드는 3가집 방법
//1. 해당 엔티티를 준영속 상태로 전환
em.detach(entity);
//2.영속성 컨텍스트를 초기화
em.clear()
//3. 영속성 컨텍스트를 종료
em.close
4. 삭제(Removed) : 삭제된 상태
em.remove(entity);
영속성 컨텍스트의 구조
영속성 컨텍스트는 1차 캐시 저장소, SQL 저장소로 나누어 집니다.
1차 캐시 저장소
엔티티를 조회하거나 저장할 경우 해당 엔티티는 1차 캐시에 저장됩니다.
1차 캐시에 저장되면 해당 엔티티는 영속 상태가 되며 영속성 컨텍스트가 관리하는 대상이 됩니다.
쿼리문 저장소
insert, update, delete등.. 여러 쿼리문을 저장했다가 commit시 한번에 처리합니다.
DB 접근 회수를 최소화하고 성능상 이점을 얻을 수 있습니다.
영속성 컨텍스트의 기능
1차 캐시
엔티티를 조회하거나 저장할 경우 해당 엔티티는 1차 캐시에 저장됩니다. 그리고 해당 엔티티를 조회 할 때, 1차 캐시에 저장되어 있다면 DB를 거치지 않고 1차 캐시 저장소에서 꺼내 사용합니다.
1차 캐시는 일종의 Map 형태로 관리되며, 엔티티의 @Id 어노테이션이 선언된 필드는 Key가 되고, instance 값이 value가 됩니다.
@id | Instance |
12 | entity@15db9742 |
15 | entity@19db7415 |
동일성 보장
Employee emp1 = employeeDao.findById(12).orElse(null);
Employee emp2 = employeeDao.findById(12).orElse(null);
System.out.println(emp1 == emp2); // true
id가 12인 Employee 엔티티 조회 시, 동일한 instance를 반환하여 동일성을 보장합니다.
트랜잭션을 지원하는 쓰기지연
엔티티 저장, 수정, 삭제 메소드를 실행할 경우 SQL 저장소에 Query문을 저장하고 있다가 flush()하고 commit()할 때 DB에 반영합니다.
변경 감지
엔티티 메니저는 update메소드가 정의되어 있지 않습니다. 영속화 된 엔티티에 변경사항이 생긴 경우, 변경 감지를 할 뿐입니다.
엔티티 1차 캐시시 엔티티에 대한 참조와 엔티티를 처음 영속상태로 만들었을 떄의 복사본을 가지고 있습니다.
flush()가 호출되면 영속화된 엔티티와 복사본을 비교하여 변경된 값이 있다면 update 쿼리를 생성하여, SQL 저장소에 저장하고 DB에 전달할 때, 함께 보냅니다.
지연 로딩(Lazy Loading)과 프록시(Proxy)
지연 로딩은 참조하는 객체를 Join하지 않고 조회 했다가 참조 객체 접근 시, Select하는 전략입니다.
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private String name;
@OneToMany(fetch = FetchType.LAZY)
private Department department;
}
Employee 엔티티는 Department(부서)를 참조하고 Lazy 패치전략을 사용하고 있습니다.
Employee 엔티티를 조회하면 department 멤버변수에는 프록시 객체가 저장됩니다.
프록시 객체란?
전략에 따라 참조 관계를 맺고있는 객체에 실제 엔티티 대신 저장된 위장 엔티티를 의미합니다.
프록시 객체에 접근 할 때, 영속성 컨텍스트에 참조 엔티티가 생성되어 있지 않다면, DB Select하여 생성합니다.
이를 프록시 초기화라고 합니다.
패치 전략에는 LAZY와 EAGER이 있습니다.
EAGER 전략은 객체 조회 시 참조 엔티티를 Join하여 함께 조회하는 전략을 의미합니다.
'IT > JPA & Hibernate' 카테고리의 다른 글
[JPA] 엔티티 매핑 어노테이션 정리 (0) | 2021.05.10 |
---|---|
[JPA] 기본키 자동 생성 전략(Primary Key) (0) | 2021.05.10 |
[JPA] @MappedSuperclass 사용법 (0) | 2021.05.08 |
[JPA] 상속 관계 매핑 (0) | 2021.05.08 |
[JPA] Hibernate 연동 방법 (0) | 2021.05.05 |