JPA(Java Persistence API) 란, 자바 진영의 ORM 기술 표준 명세로서 객체지향 언어인 자바와 관계형 데이터베이스 간 데이터를 다루는 방식의 차이점으로 인해 발생하는 문제점을 해결해주고, 이에 더해 자바 코드로 SQL을 다룰 수 있도록 함으로써, SQL 의존적인 개발에서 벗어나 객체지향 언어인 자바 중심의 개발을 할 수 있도록 도와줍니다.
JPA 는 표준 명세이기 때문에 다양한 구현체가 존재하며, 대표적으로 hibernate, eclipse link 등이 존재합니다.
JPA 의 사용 이유
패러다임의 불일치
자바에서는 객체를, 데이터베이스에서는 테이블을 기준으로 설계가 진행되며, 데이터를 다루는 방식 또한 다릅니다. 주요한 차이점은 다음과 같습니다.
[연관된 데이터] 객체에서는 각 객체들간의 관계를 직접 참조를 통해 관계를 맺고, 참조를 통해 탐색할 수 있지만, 관계형 데이터베이스에서는 테이블간 관계를 외래키를 통해 맺고, join 연산을 통해 탐색하여야 합니다.
[상속 구조] 객체에서는 상속을 통해 기존 클래스를 재사용하여 확장해나갈 수 있지만, 데이터베이스에서는 상속이라는 개념이 존재하지 않습니다.
[컬렉션 형태의 데이터] 객체에서는 list 나 set 등 여러 데이터가 들어간 타입을 가질 수 있지만, 기본적으로 정규화된 테이블에서는 하나의 값만 가질 수 있습니다.
JPA 는 이러한 패러다임의 불일치로 인한 문제를 해결해주어 자바 코드로 데이터베이스를 편하게 다룰 수 있도록 해줍니다.
생산성
기존에는 자바에서 데이터베이스를 다루기 위해서는 SQL 을 직접 작성하여야 했습니다. SQL 을 직접 작성하는 것의 문제점은 요구사항의 변경이 생겼을 때 관련된 SQL 을 모두 변경해야 한다는 것이었습니다.
JPA 에서는 SQL 을 직접 사용하기 보다는 매핑 정보를 통해 SQL 을 자동 생성하여, 비교적 작은 범위의 변경으로 해결할 수 있습니다.
JPA 의 기본 구성 요소
Entity
JPA 에서는 테이블과 매핑되는 객체를 Entity 라 정의합니다. 테이블과 매핑이 되어야 하기 때문에, 매핑 관련 정보들을 Entity 에 작성하면, JPA 에서는 이를 통해 테이블과의 매핑을 수행하게 됩니다.
EntityManager
EntityManager 는 Entity 를 직접 관리하는 주체로서, JPA 의 가장 핵심적인 부분이라고 할 수 있습니다. Entity 의 생명 주기를 비롯하여 쿼리 실행 등을 전담하고 있습니다.
EntityManager 는 일반적으로 트랜잭션 단위로 생성되고, 사용되기 때문에 스레드간 공유를 하게 된다면 문제가 발생할 수 있습니다.
EntityManagerFactory
EntityManager 인스턴스를 만들어주는 객체입니다. 데이터베이스의 설정과 기본적인 Entity 들의 매핑 정보를 로딩/저장하며, 이는 이후 EntityManager 에서 트랜잭션을 사용하거나, Entity 를 관리할 때 사용되게 되며, 기본적으로 데이터베이스당 하나만 존재하고, 여러 EntityManager 에서 사용되기 때문에 스레드간 공유에도 안전하도록 설계되었습니다.
참고
Spring 과 통합하여 사용시에는, 스프링에서 제공하는 JpaTransactionManager 내부에 EntityManagerFactory 가 존재합니다. 기본적으로 다음 순서로 동작합니다.
1. @Transactional 메서드 호출시 EntityManager 를 Factory 를 통해 가져옵니다. 2. EntityManager 에서는 Datasource 에서 커넥션 풀을 통해 커넥션을 획득합니다. 3. EntityManager 에서는 트랜잭션 시작을 위해 TransactionManager 를 통해 트랜잭션을 시작합니다. 4. 커밋이나 롤백이 필요시 TransactionManager 를 통해 진행하며, 이후 트랜잭션을 종료하고 커넥션 반환 후에 EntityManager 가 종료됩니다.