JPA - 기본 개념 1편

minseok·2023년 3월 1일
0

학습 영상 👍어라운드 허브 스튜디오 유튜브👍
https://www.youtube.com/watch?v=5DAW3CCZ_rU




Q. 왜 JPA 학습을 하나요?

  1. 많은 회사에서 ORM 기술을 사용합니다.
    현재 사용가능한 기술 java, spring이여서 JPA가 강제되며 가장 많이 사용하는 것 같은 구현체로 hibernate를 선택
  1. 서비스의 안전성, 생산성이 높아질 것 같다.
    비즈니스 로직을 코드단으로 유도하여 테스트에 용이하며
    객체지향 설계에 적합 그리고
    컴파일 시점에 에러를 검출하여 열심히 학습하면
    업무가 편해질 것 같습니다.






📈 JPA

Java persistence api의 약자이며 Java에서 ORM을 사용하기 위한 인터페이스입니다.
구현체로는 Eclipse Link, Data Nucles, Hibernate가 있으며
국내에서는 Hibernate가 많이 사용되는 것으로 추측

현업에서는 JPA를 더 사용하기 쉽게 제공해주는 Spring data jpa를 사용합니다.
하지만 사용하기 쉽게 추상화가 되어있어 원리의 파악을 위해서는 hibernate-core같은 구현체만 사용하는 것이 좋습니다.(hibernate 기준)





🧬 JPA 구조

https://www.tutorialspoint.com/jpa/jpa_architecture.htm



🏭 Entity Manager Factory
1개의 persistence-unit(DB)에 1개의 Entity Manager Factory를 가집니다. Spring Data Jpa에서는 생성 비용이 비싸 singleton 패턴을 사용하여 운용이 되며
Entity Manger를 Connection Pooling 방식을 사용하여 관리합니다.


👩‍🏭 Entity Manager
DB, 영속성 컨텍스트(Persistence Context)와 상호작용을 하는 객체이며 Entity Manager와 1 : N의 관계를 가집니다. client의 요청마다 Entity Manager를 제공해줍니다.


🚧 Transaction(Entity Transaction)
Entity Manager와 1 : 1 관계이며 ACID를 보장받기 위해 사용됩니다.


🪆 Entity
Java 객체와 DB의 Table을 Mapping한 기술입니다.
Entity 1개가 1개의 Table Row를 표현합니다.


📦 Persistence Context(Persistence)
영속성 컨텍스트, 1차 캐시로도 불립니다.
Entity Manager와 1 : 1 관계이며 Entity Manager와 같은 생명주기를 가지며
Entity의 식별자 + Entity Type을 Key로 사용하는 영속 객체의 집합입니다.


🧱 Query
Database에서 데이터를 가져오거나 변경하기 위해 사용되는 객체입니다.
영속 객체를 DB에 반영하거나 data를 조회시 사용됩니다.





📦 Persistence Context(영속성 컨텍스트)

JPA가 관리하는 Entity 객체의 집합입니다.
Entity로 정의하기로 한 타입의 객체가 영속성 컨텍스트에 들어오면
Entity의 상태가 추적되며 EntityManager가 Transaction을
commit하면 현재의 Entity의 상태를 Query객체를 사용하여
SQL쿼리를 날려 해당 Record의 상태를 업데이트 합니다.

또한 영속성 컨텍스트에 들어온 Entity를 영속 객체라고도 표현합니다.





🎭 proxy

Proxy 객체에서 실제 객체의 참조를 가집니다.
실제 객체의 method 호출 시 영속석 컨텍스트를 통해 proxy의 target을 초기화합니다.

초기화 시 proxy 객체 자체가 변경되는 것이 아니라
proxy 객체가 가지고 있는 target을 초기화합니다.

비교를 원할때 식별자 값으로 조회하는 경우
Proxy 객체와 원본 객체 모두 동등성 비교에서 true를 반환합니다.

그리고 영속성 컨텍스트를 통해 초기화하므로 영속성 컨텍스트영역안의 영속 상태에서만 초기화가 가능합니다.




🐇 즉시 로딩

비즈니스 로직상에서 함께 Join되는 경우가 많을때 이점이 있습니다.

허나 즉시 로딩을 사용하면 예상하지 못한 SQL이 발생하며
JPQL에서는 N+1 문제를 일으킵니다.
김영한님께서는 그냥 사용하지 말고 LAZY로 통일하라고 권장하십니다.






🐢 늦은 로딩

EntityManager의 find()는 DB의 records를 Entity에 Mapping하여 즉시 반환합니다.
하지만 getRefrence()는 실제 records를 바로 반환하는 대신 Proxy 객체를 반환합니다.
바로 조회 쿼리도 나가지않고 Proxy객체의 상태에 접근시에 조회 쿼리를 날립니다.

Entity들과 관계를 맺는 객체들을 모두 한번에 조회하지 않고
부분적으로 조회를 하고싶을때 사용되는 기술입니다.

상속을 통하여 Proxy객체를 생성하므로 Entity가 final keyword를 사용을 할 수 없고
기본 생성자가 필요합니다.





🔑 기본 키 생성 전략 Identity

기본 키 생성 전략이란 JPA에서 새로운 영속 객체가 생성이 되면 해당 객체를 식별 할 값이 필요하며 기본 키를 식별자로 사용합니다.
영속성 컨텍스트에서는 Entity의 식별자를 @Id + Entity Type을 기본키로 사용합니다.

'직접 할당 방식', 'Identity', 'Sequence' 같이 여러 가지 전략이 존재하며 3가지만 알아보겠습니다.


  1. '직접 할당 방식'은 기본 키를 직접 생성하는 방식으로 영속 객체가 될 때
    직접 값을 넣어줍니다.
  1. 'Identity'는 MySql기준으로 auto_increment를 @Id값으로 사용합니다.
    특이한 점은 transaction이 commit이 되면 Insert 쿼리를 생성하지만
    해당 전략은 persist() 호출 타이밍에 Insert 쿼리가 생성됩니다. (DB에서 @Id값을 가져옴)
  1. 'Auto'는 JPA에서 DB에 따라서 적절한 생성 전략을 선택해줍니다. (비추)

많은 전략이 있지만 공통점은 어떠한 전략을 선택하였어도
영속 객체가 될때 기본 키가 강제됩니다.

hibernate에서는 @id이 선언된 필드가 Null인 상태로 영속객체가 되면
아래와 같은 예외를 던집니다.

org.hibernate.id.IdentifierGenerationException


profile
즐겁게 개발하기

0개의 댓글