JPA 소개

- JPA(Java Persistent API)
- 자바 진영의 ORM 기술 표준
- Application과 JDBC(Java Database Connectivity) 사이에서 동작
- ORM(Object Relational Mapping)
- 객체는 객체대로, 관계형 DB는 관계형 DB대로 설계하고, ORM 프레임워크가 중간에서 매핑하는 역할 수행
JPA 필요성
- SQL 중심적인 개발 → 객체 중심적인 개발
- JPA 이전에는 객체를 관계형 DB에 관리하기 위해서는 반복적인 SQL 필요
- 객체의 Field가 수정되면 그에 맞춰 SQL도 변경 필요 ⇒ 개발이 SQL에 의존적
- 생산성
- 유지보수
- 어느 객체의 Field가 추가되거나 변경되어도 모든 SQL을 수정하지 않고 Entity만 수정하면 해결됩니다.
- 패러다임 불일치 해결
- 객체지향 프로그래밍은 상속과 다형성 등을 지원. 관계형 DB는 이를 지원하지 않기에 이 차이를 극복하기 위해 SQL 매핑이 필요
- 상속
- 객체는 상속을 통해 구현하고, 테이블은 슈퍼타입과 서브타입으로 나뉘어져 있으며, 객체 하나를 불러오기 위해서는 두개의 테이블을 조인해야하고, 저장하기 위해서는 두개의 테이블에 INSERT 해줘야함
- 연관관계
- 객체의 경우 참조를 사용하여 연관관계를 표현하지만, 테이블은 FK를 사용하여 연관관계를 표현함. 때문에 객체를 개발할 때 테이블에 맞추어 참조가 아닌 FK 필드로 모델링하는 경우가 많음
- 객체 그래프 탐색과 Entity 신뢰 문제
- SQL을 실행할 마다 탐색 범위가 결정되기 때문에 어느 관계까지 객체가 존재하는지 판단할 수 없는 문제가 발생하여 Entity를 신뢰할 수 없게 됨 ⇒ 계층형 아키텍처를 설계해서 진정한 의미의 계층 분할이 어려움
- 객체 비교
- 동일한 ID를 가진 객체를 조회하더라도 매번 새로운 DAO 객체가 생성되기 때문에 객체 비교가 어려움
- ⇒ 객체답게 모델링 할수록 SQL과 매핑하는 비용만 늘어나고 설계가 SQL에 의존적이게 됨
- 성능
- 1차 캐시와 동일성 보장
- 동일 트랙잭션(영속성 Context) 내에서는 캐싱을 통해 같은 Entity를 반환
- 트랜잭션을 지원하는 쓰기 지연 (Transactional Write-behind)
- 트랜잭션을 커밋할 때까지 SQL을 모으다가 JDBC BATCH SQL 기능을 사용해서 모은 SQL을 한 번에 전송
- 즉시 로딩과 지연 로딩
- 즉시 로딩은 JOIN SQL로 연관 객체까지 한 번에 미리 조회
- 지연 로딩은 객체가 실제로 사용될 때 로딩
- 데이터 접근 추상화 벤더 독립성
- 특정 DB에 종속적이지 않음
- 추가로 JPA에 DB Dialect(방언)을 설정해주면 각각의 DB가 제공하는 SQL 문법과 함수를 사용할 수 있음
JPA 구동 방식

persistence.xml
파일을 조회해서 설정에 맞게 DB 구성
- DB 접근을 위해 커넥션을 생성해주는
EntityManagerFactory
생성
- 각 DB 당 하나만 생성해서 Application 전체에 공유
- 각 커넥션마다 EntityManager가 생성되어 트랜잭션 처리 후 소멸
- 쓰레드 간 공유하면 안되며 각각의 커넥션마다 생성 후 다 사용하면 버려야함