JPA Java Persistence API
ORM Object-relational mapping
- 객체 관계 매핑
- 객체는 객체대로 설계
- 관계형 데이터베이스는 관계형 데이터베이스대로 설계
- ORM 프레임워크가 중간에서 매핑
JPA는 애플리케이션과 JDBC 사이에서 동작
JPA 동작 - 저장
JPA 동작 - 조회
JPA 표준 명세
- 인터페이스의 모음
- JPA 표준 명세를 구현한 구현체
- 하이버네이트
JPA 장점
- SQL 중심 개발 → 객체 중심 개발
- 생산성, 유지보수, 성능, 표준
생산성 - CRUD
- 저장:
jpa.persist(member)
- 조회:
Member member = jpa.find(memberId)
- 수정:
member.setName(”변경할 이름”)
- 삭제:
jpa.remove(member)
유지보수
- 기존: 필드 변경시 모든 SQL 수정
- JPA: 필드만 추가하면 된다. SQL 은 JPA 가 처리
패러다임 (틀) 의 불일치 해결
JPA 와 상속
상속 - 저장
- 개발자
- JPA 자동 처리
INSERT INTO ITEM …
INSERT INTO ALBUM …
- 각각의 쿼리 2개 생성
상속 - 조회
- 개발자
Album album = jpa.find(Album.class, albumId);
- Album 클래스와 PK 값을 넘긴다.
- JPA 자동 처리
SELECT I.*, A.* FROM ITEM I JOIN ALBUM A ON I.ITEM_ID = A.ITEM_ID
- ITEM 테이블과 ALBUM 테이블을 조인해서 데이터 조회
JPA 연관관계, 객체 그래프 탐색
- 연관관계 저장
member.setTeam(team);
jpa.persist(member);
- 객체 그래프 탐색
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();
신뢰할 수 있는 엔티티 계층
public void process() {
Member member = memberDAO.find(memberId);
member.getTeam();
member.getOrder().getDelivery();
}
- JPA 사용하지 않았을 때 엔티티 신뢰 문제 발생
- DAO 안에서 어떤 쿼리를 날려서 어떤 데이터를 가져오는지 확인 필요
- member 객체를 신뢰할 수 없다.
- JPA 사용시 엔티티 신뢰 가능
- 자유로운 객체 그래프 탐색
- member 객체 신뢰 가능
JPA 비교하기
String memberId = "100";
Member member1 = jpa.find(Member.class, memberId);
Member member2 = jpa.find(Member.class, memberId);
member1 == member2;
- 동일한 트랜잭션에서 조회한 엔티티는 같음을 보장
- 마치 자바 컬렉션의 동등 비교와 동일
성능 최적화 기능
- 1차 캐시와 동일성 (identity) 보장
- 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
- 지연 로딩 (Lazy Loading)
1차 캐시와 동일성 보장
String memberId = "100";
Member member1 = jpa.find(Member.class, memberId);
Member member2 = jpa.find(Member.class, memberId);
member1 == member2;
트랜잭션을 지원하는 쓰기 지연 - INSERT
- 트랜잭션을 커밋할 때까지 INSERT SQL 을 모은다.
- JDBC BATCH SQL 기능을 사용해서 한번에 SQL 전송
transaction.begin();
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
transaction.commit();
지연 로딩과 즉시 로딩
Member member = memberDAO.find(memberId);
Team team = member.getTeam();
String teamName = team.getName();
Member member = memberDAO.find(memberId);
Team team = member.getTeam();
String teamName = team.getName();
- 즉시 로딩: JOIN SQL 로 한번에 연관된 객체끼리 미리 조회