의문점 공부하기/📌 Java

JPA

아리빠 2023. 10. 5. 16:07

JPA: Java Persistence API

JPA는 자바 진영에서 ORM 기술 표준으로 사용하는 인터페이스의 모음

ORM이란?
ORM은 DB와 실제 객체간의 간격을 매핑해주는 Object Relational Mapping 기술

+DB의 CRUD 동작을 모두 메소드로 처리할 수 있게 한다.

JPA는 인터페이스의 모음으로, 구현체가 따로 없다. 일반적으로 사용되는 구현체는 Hibernate가 존재

 

JPA를 왜 써야하나?
JPA 장점
Query문 작성 실수를 피할 수 있다.
Query같은 경우는 컴파일 시, 오류가 여부 검사가 어렵다

실제로 해당 쿼리가 동작하는 기능이 수행되어야 하기 때문에, 배포 후 오류가 발견된다면...?

협업 상황 시, 다른 사람 코드를 이해하기가 더 쉽다.

JPA 단점
정형화 되어있는 쿼리 튜닝이 일어나기 때문에, 결국에 Query문을 직접 작성해야 하는 경우가 생길 수 있다.
서비스가 JPA에 의존하게 된다.
서비스의 DB 구조가 복잡할 경우 JPA의 이용에도 많이 복잡할 수 있다.


웹 어플리케이션이 구동하는 시점에 EntityManagerFactory 를 생성하여 가지고 있으며, 사용자의 요청이 있을 때 EntityManager를 생성하여 커넥션 풀(Connection Pool) 을 사용해서 DB를 핸들링 하게 됩니다.

 

 "영속성 컨텍스트"란?

 

영속성?

-엔티티를 영구 저장하는 환경
 
- EntityManager.persist(entity);
→ 좀 더 풀어서 설명하면 DB에 저장한다기보다는 영속성 컨텍스트를 통해 엔티티를 영속화 한다는 의미
 -- 영속성 컨텍스트에 엔티티를 저장한다는 말
-영속성 컨텍스트는 논리적인 개념.
-눈에 보이지 않는다.
-엔티티 매니저를 통해서 영속성 컨텍스트에 접근
 --J2SE 환경

 

컨텍스트?

 

-누가 무엇을 어떤 의도를 가지고 언제 행위를 하였는지에 대한 정보를 통칭


-런타임 시 생성되는 정보

 

-영속성 컨텍스트는 런타임 시 JPA와 함께 사용되는 개발자의 의도에 대한 별도의 기억장치에 보존되어 있는 정보

 

영속성 컨텍스트는 생명 주기를 가지고 있다. 생명 주기는 비영속, 영속, 준영속, 삭제 상태로 4개가 존재

-비영속(new) : 영속성 컨텍스트와 상관없는 상태, 객체를 생성만 한 상태

// 객체를 생성한 상태 (비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");

-영속(managed) : 영속성 컨텍스트에 저장되어 관리되고 있는 상태

영속 상태가 된다고 바로 DB에 쿼리가 날라가지 않음

트랜잭션의 commit 시점에 영속성 컨텍스트에 있는 정보들이 DB쿼리로 보내짐

// 객체를 생성한 상태 (비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
// 객체를 저장한 상태 (영속)
entityManager.persist(member);

-준영속(detached) : 영속성 컨텍스트에서 분리된 상태

영속성 컨텍스트에서 지운 상태

// 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
entityManager.detach(member);

-삭제(removed) : 실제 DB삭제를 요청한 상태

// 객체를 삭제한 상태
entityManager.remove(member);

영속 상태와 준영속 상태


-영속 상태란
--entityManager.persist(); 로 영속성 컨텍스트에 저장된 상태
--entityManager.find(); 로 조회할 때 영속성 컨텍스트 1차 캐시에 없어서 DB에서 조회한 후 해당 Entity를 1차 캐시에 올라 상태 (엔티티 매니저가 관리하는 상태)

 

-준영속 상태
--영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)된 상태
--준영속 상태에서는 영속성 컨텍스트가 제공하는 기능을 사용하지 못한다.
 ---Dirty Checking, Update Query

 

--entityManager.find(): 1차 캐시에 없으므로 DB에서 조회한 Entity를 1차 캐시에 넣는다. (영속 상태)
--변경 감지(Dirty Checking)
---이름 변경에 대한 Entity 데이터 변화를 감지한다.
---1차 캐시의 Entity와 Snapshot이 다른 것을 감지하고 UPDATE Query를 날린다

-준영속 상태로 만드는 방법 (영속 -> 준영속)
--entityManager.detach(entity): 특정 엔티티만 준영속 상태로 전환
--entityManager.clear(): 영속성 컨텍스트를 완전히 초기화
--entityManager.close(): 영속성 컨텍스트를 종료

 

 Detach

-entityManager.detach(); : 해당 Entity를 영속성 컨텍스트에서 분리

Transaction commit에서 아무 일도 발생하지 않음

=> Entity가 변경되었지만 실제로 Update Query가 나가지 않음(쓸일 거의 없을듯..?)

 

Clear

-entityManager.clear();: EntityManager 안에 있는 영속성 컨텍스트를 모두 지운다.
--영속성 컨텍스트를 완전히 초기화
-clear 후 같은 Entity를 다시 조회할 때는 SELECT Query가 다시 나간다.
--총 2번의 SELECT 쿼리가 발생한다.
--clear는 1차 캐시에 상관없이 쿼리를 확인하고 싶을 때 즉, testcase 작성 시에 도움이 된다.

 

Close
-영속성 컨텍스트를 종료시킨다.
-JPA 의 관리 대상이 아니게 된다.