Q. JPA의 영속성 컨텍스트에 대해서 설명해 주세요.
영속성 컨텍스트란 엔티티를 영구 저장하는 환경이라는 뜻입니다.
애플리케이션과 데이터베이스 사이에서 객체를 보관하는 가상의 데이터베이스 같은 역할을 합니다.
엔티티 매니저를 통해 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리합니다.
트랜잭션이 끝나면 데이터베이스에 반영합니다.
특징
- 엔티티 매니저를 생성할 때 하나 만들어진다.
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근하고 관리할 수 있다.
- 영속성 컨텍스트는 엔티티를 식별자 값으로 구분하기 때문에 영속 상태는 식별자 값이 반드시 있어야 한다.
- JPA는 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영한다. (flush)
엔티티의 생명주기
- 비영속(new/transient): 영속성 컨텍스트와 전혀 관계가 없는 상태. 엔티티 객체를 생성했지만 아직 영속성 컨텍스트에 저장하지 않은 상태
- 영속(managed): 엔티티 매니저를 통해 엔티티를 영속성 컨텍스트에 저장한 상태. 영속성 컨텍스트에 의해 관리된다는 뜻
- 준영속(detached): 영속성 컨텍스트에 저장되었다가 분리된 상태. 영속성 컨텍스트가 관리하던 영속 상태의 엔티티를 더이상 관리하지 않으면 준영속 상태가 됨.
- 준영속 상태 특징 :1차 캐시, 쓰기 지연, 변경 감지, 지연 로딩을 포함한 영속성 컨텍스트가 제공하는 어떠한 기능도 동작하지 않는다. 식별자 값을 가지고 있다.
- 삭제(removed): 삭제된 상태. 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제한다.
영속성 컨텍스트가 엔티티를 관리할 때 장점
1. 1차 캐시
영속성 컨텍스트 내부에 캐시가 있다. (1차 캐시) 영속 상태의 엔티티를 이곳에 저장하고 1차 캐시에 엔티티가 있으면 조회하고, 없으면 데이터베이스에서 조회한다. 조회된 데이터는 엔티티를 생성해 1차 캐시에 저장한다.
2. 동일성 보장
영속성 컨텍스트는 엔티티의 동일성을 보장한다. 동일성 비교 : 실제 인스턴스가 같다. ==, 동등성 비교: 실제 인스턴스는 다를 수 있지만 인스턴스가 가지고 있는 값이 같다. equals()
3. 트랜잭션을 지원하는 쓰기 지연
엔티티 매니저는 트랜잭션을 커밋하기 직전까지 내부 쿼리 저장소에 INSERT SQL을 모아둔다. 그리고 트랜잭션을 커밋할 때 모아둔 쿼리를 DB에 보낸다. 이것을 트랜잭션을 지원하는 쓰기 지연이라고 한다.
4. 변경 감지
JPA로 엔티티를 수정할 때는 단순히 엔티티를 조회해서 데이터를 변경하면 된다.
- 변경감지의 흐름
1. 트랙잭션을 커밋하면 엔티티 매니저 내부에서 먼저 플러시가 호출된다.
2. 엔티티와 스냅샷을 비교하여 변경된 엔티티를 찾는다.
3. 변경된 엔티티가 있으면 수정 쿼리를 생성해서 쓰기 지연 SQL 저장소에 저장한다.
4. 쓰기 지연 저장소의 SQL을 플러시한다.
5. 데이터베이스 트랜잭션을 커밋한다.
5. 지연 로딩
플러시
플러시는 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영한다. 영속성 컨텍스트의 엔티티를 지우는게 아니라 변경 내용을 데이터베이스에 동기화하는 것이다.
플러시의 흐름
1. 변경 감지가 동작해서 스냅샷과 비교해서 수정된 엔티티를 찾는다.
2. 수정된 엔티티에 대해서 수정 쿼리를 만들거 SQL 저장소에 등록한다.
3. 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송한다.
플러시하는 방법
1. em.flush()
2. 트랙잭션 커밋시 자동 호출
3. JPQL 쿼리 실행시 자동 호출
Q. 제네릭에 대해서 설명하고, 컬렉션 클래스에서 왜 제네릭을 사용하는 지 설명해주세요.
제네릭(generic)은 데이터 타입을 일반화하는 것을 의미합니다. 한 번의 정의로 여러 종류의 데이터의 타입을 다룰 수 있습니다. 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정합니다.
예를들어 아래와 같이 ArrayList<E> 형태로 클래스가 정의되어 있다면, 사용자는 데이터로 String을 사용할 때는 ArrayList<String>으로, Integer를 사용할 때는 ArrayList<Integer>로 지정하여 사용할 수 있습니다.
컴파일 시에 미리 타입 검사를 하면 다음과 같은 장점이 있습니다.
1. 클래스나 메소드 내부에서 사용되는 객체의 타입 안정성을 높일 수 있다.
2. 반환값에 대한 타입 변환 및 타입 검사에 들어가는 노력을 줄일 수 있다.
제네릭의 장점
1. 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있다.
2. 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 변환해줄 필요가 없어 관리가 편하다.
3. 비슷한 기능을 지원하는 경우 코드 재사용성이 높아진다.
자바 코드에서 선언되고 사용된 제네릭 타입은 컴파일 시 컴파일러에 의해 자동으로 검사되어 타입 변환됩니다.
그리고 코드 내의 모든 제네릭 타입은 제거되고, 컴파일된 클래스 파일에는 어떤 제네릭 타입도 남아있지 않게 됩니다.
이렇게 동작하는 이유는 제네릭을 사용하지 않는 코드와의 호환성을 유지하기 위함입니다.
컬렉션 클래스에서 제네릭을 사용하는 이유
타입에 따라 클래스를 생성할 필요가 없고, 코드 중복을 최소화할 수 있다.
+ 와일드카드 <?>
어떤 타입이든 상관 없다는 의미. 보통 데이터가 아닌 기능의 사용에만 관심이 있는 경우에 사용한다.
참고
https://st-lab.tistory.com/153
http://www.tcpschool.com/java/java_generic_concept
'Spring' 카테고리의 다른 글
[Spring] 트랜잭션 & TCP와 UDP (0) | 2023.07.26 |
---|---|
[Spring] 의존성 주입(DI) (0) | 2023.07.25 |
[Spring] Rest Client & @SpringBootTest와 @WebMvcTest (0) | 2023.07.25 |
[Spring] DI와 예외처리 (0) | 2023.07.20 |
[Spring] @Transactional 어노테이션 (0) | 2023.04.18 |