DB와 SQL의 의존성 문제
DB를 직접 다룰 때는 SQL에 의존적이기 때문에 데이터베이스가 변경될 경우 코드도 많이 수정해야 하는 문제가 생길 수 있다.
이러한 반복적이고 번거로운 SQL 작업을 줄이기 위해 ORM(Object Relational Mapping)이 등장했다.
JPA (Java Persistence API)
JPA는 Java에서 사용하는 ORM 기술의 표준 명세이다.
대표적인 구현체로는 Hibernate가 있다.
Entity 이해하기
Entity는 데이터베이스의 테이블과 매핑되는 JPA에서 관리되는 클래스이다.
영속성 컨텍스트
영속성 컨텍스트는 Entity를 효율적으로 관리하기 위한 공간이다.
영속성(Persistence)은 객체의 생명 주기나 위치를 자유롭게 관리할 수 있는 객체의 성질을 의미한다.
EntityManager
영속성 컨텍스트에서 Entity 객체들을 조작하기 위해서는 EntityManager가 필요하다.
일반적으로 데이터베이스 하나당 하나의 EntityManagerFactory가 생성되며, 이를 통해 여러 EntityManager를 생성할 수 있다.
JPA 트랜잭션
트랜잭션은 DB 데이터를 안전하게 관리하기 위한 개념으로, 무결성과 정합성을 유지하는 역할을 한다.
JPA는 이러한 트랜잭션 개념을 도입하여, 쓰기 지연 저장소(ActionQueue)에 데이터를 저장하고 있다가 커밋 시점에 한꺼번에 데이터베이스에 반영하여 효율적으로 처리한다.
1차 캐시
영속성 컨텍스트는 내부적으로 1차 캐시 저장소를 가지고 있다.
예를 들어, em.persist(entity);
메서드가 호출되면 해당 Entity는 1차 캐시에 저장된다.
만약 1차 캐시에 요청한 데이터가 없으면, 데이터베이스에 요청하여 데이터를 가져온다.
em.remove(entity);
를 호출하면 삭제할 Entity가 DELETED 상태가 되고, 트랜잭션 커밋 후에 데이터베이스에서 삭제된다.- 트랜잭션 중에 데이터를 조회하고, Entity 객체의 값을 변경하면,
persist
를 하지 않아도 JPA가 내부적으로 loadedState와 비교하여 변경을 감지하여 Update SQL을 생성하고 DB에 반영한다. 이를 변경 감지(Dirty Checking)라고 한다. - 영속(Managed) 상태일 때만 변경 감지가 이루어진다.
Entity의 상태
- 비영속(Transient):
new
연산자를 통해 생성된, 인스턴스화된 Entity 객체를 의미한다. - 영속(Managed):
em.persist(entity);
를 통해 EntityManager가 Entity를 영속성 컨텍스트에 저장하고 관리하는 상태이다. - 준영속(Detached): 한때 영속성 컨텍스트에 저장되었으나, 더 이상 관리되지 않는 상태를 의미한다.
준영속 상태로 전환하는 방법
em.detach(entity);
: 특정 엔티티를 영속성 컨텍스트에서 분리한다.em.clear();
: 영속성 컨텍스트를 초기화하여 모든 엔티티를 준영속 상태로 만든다.em.close();
: 영속성 컨텍스트를 종료하여 모든 엔티티를 준영속 상태로 만든다.
그 외 상태
em.merge(entity);
: 비영속 또는 준영속 상태의 엔티티를 영속성 컨텍스트로 다시 가져와 없다면 데이터베이스에 저장, 있다면 수정 작업을 한다.em.remove(entity);
: 엔티티를 삭제 상태로 만든다.