
JPA(Java Persistence API)는 자바에서 관계형 데이터베이스와의 상호작용을 간소화하는 자바 진영의 ORM(Object-Relational Mapping) 기술입니다. ORM은 객체 지향 프로그래밍 언어의 객체와 관계형 데이터베이스의 테이블 간의 매핑을 자동으로 처리하는 기술을 말합니다.
객체-관계 매핑 (ORM): JPA는 자바 객체와 데이터베이스 테이블 간의 매핑을 지원합니다. 개발자는 객체 지향적인 방식으로 데이터를 다룰 수 있으며, JPA가 해당 객체와 데이터베이스 레코드 간의 매핑을 처리합니다.
"영속성"은 데이터의 지속성이나 영구성을 의미합니다. 객체의 상태가 프로그램의 실행이나 특정 작업을 넘어서 지속되는 것을 말합니다.
JPA에서는 영속성이 주로 엔티티 객체(Entity Object)의 상태를 지속적으로 관리하는 개념으로 사용됩니다. 엔티티의 상태가 데이터베이스에 저장되어 지속되는 것을 말합니다.
간단한 예시를 통해 설명하면, 한 번 조회한 엔티티는 영속성 컨텍스트의 1차 캐시에 저장되며, 이후 동일한 엔티티를 조회할 때는 1차 캐시에서 가져와 데이터베이스에 다시 접근하지 않습니다. 이로써 성능이 향상되고 데이터베이스 부하가 감소합니다.
중요한 점은 1차 캐시는 트랜잭션 범위 내에서만 유효하며, 트랜잭션이 종료될 때 영속성 컨텍스트의 1차 캐시도 초기화됩니다.


엔티티 생명 주기(4가지 상태)
- 비영속(new/transient)
영속성 컨텍스트와 연관이 없는 상태
- 영속(managed)
영속성 컨텍스트에서 관리 중인 상태
- 준영속(detached)
영속성 컨텍스트에 저장되어 있었으나 분리된 상태
- 삭제(remove)
영속성 컨텍스트에서 완전히 삭제된 상태

@PersistenceContext
private final EntityManager em;
- @PersistenceContext 란?
EntityManager를 빈으로 주입할 때 사용하는 어노테이션입니다.
스프링에서는 영속성 관리를 위해 EntityManager가 존재합니다.
그래서 스프링 컨테이너가 시작될 때 EntityManager를 만들어서 빈으로 등록해둡니다.
이 때 스프링이 만들어둔 EntityManager를 주입받을 때 사용합니다.
@PersistenceContext로 지정된 프로퍼티에 아래 두 가지 중 한 가지로 EntityManager를 주입해줍니다.
EntityManagerFactory에서 새로운 EntityManager를 생성하거나
Transaction에 의해 기존에 생성된 EntityManager를 반환해줍니다.
- @PersistenceContext를 사용해야 하는 이유
EntityManager를 사용할 때 주의해야 할 점은 여러 쓰레드가 동시에 접근하면 동시성 문제가 발생하여 쓰레드 간에는 EntityManager를 공유해서는 안됩니다.
일반적으로 스프링은 싱글톤 기반으로 동작하기에 빈은 모든 쓰레드가 공유합니다.
그러나 @PersistenceContext으로 EntityManager를 주입받아도 동시성 문제가 발생하지 않습니다.
동시성 문제가 발생하지 않는 이유는
스프링 컨테이너가 초기화되면서 @PersistenceContext으로 주입받은 EntityManager를 Proxy로 감쌉니다.
그리고 EntityManager 호출 시 마다 Proxy를 통해 EntityManager를 생성하여 Thread-Safe를 보장합니다.
//객체만 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
//객체를 영속성 컨텍스트에 저장
em.persist(member);
//영속성 컨텍스트에서 분리 객체
em.detach(member);
em.remove(member);
public interface MemberRepository extends JpaRepository<Member, Long>{
}