- Java Persistence API
- 자바 진영의 ORM 기술 표준
- Object-relational mapping (객체 관계 매핑)
- 객체는 객체대로 설계
- 관계형 데이터베이스는 관계형 데이터베이스대로 설계
- ORM 프레임워크가 중간에서 매핑
- 대중적인 언어에는 대부분 ORM 기술이 존재
Java 애플리케이션에서 JPA에게 명령을 하면 JPA가 JDBC API를 사용해서 데이터베이스에 SQL을 호출하고 결과를 반환받는다.
만약 MemberDao에서 객체를 저장하고 싶다면 ?
- JPA에게 Member 객체를 넘긴다.
- JPA가 Member 객체를 분석한다.
- JPA가 분석을 바탕으로 적절한 Insert 쿼리를 생성한다.
- JPA가 JDBC API를 사용하여 데이터베이스에 Insert 쿼리를 보낸다.
- DB로 부터 결과를 반환받는다.
가장 큰 특징 :
1. 쿼리를 개발자가 아닌 JPA가 만들어준다.
2. 패러다임의 불일치 문제를 해결해준다.
만약 MemberDao를 조회하고 싶다면?
- JPA에게 PK값을 넘긴다.
- JPA가 적절한 Select 쿼리를 생성한다.
- JPA가 JDBC API를 사용하여 데이터베이스에 Select 쿼리를 보낸다.
- DB로 부터 결과를 반환받는다.
- ResultSet을 Member 객체에 매핑해준다.
가장 큰 특징 :
1. 쿼리를 개발자가 아닌 JPA가 만들어준다.
2. 패러다임의 불일치 문제를 해결해준다.
- JPA는 인터페이스의 모음
- JPA 2.1 표준 명세를 구현한 3가지 구현체
- 하이버네이트, EclipseLink, DataNucleus
- SQL 중심적인 개발에서 객체 중심으로 개발
- 생산성
- 유지 보수
- 패러다임의 불일치 해결
- 성능
- 데이터 접근 추상화와 벤더 독립성
- 표준
저장 : jpa.persist(member)
조회 : Member member = jpa.find(memberId)
수정 : member.setName("변경할 이름")
삭제 : jpa.remove(member)
특히 수정할 때 setName("변경할 이름")을 사용하여 원하는 이름으로 변경하였을 때 JPA에서 자동으로 Update 쿼리가 생성된다.
기존에는 필드 변경 시 모든 SQL문을 개발자가 스스로 수정해야 했다.
필드를 변경하더라도 JPA에서 알아서 수정해주기 때문에 개발자 스스로 SQL문을 수정하지 않아도 된다.
- JPA와 상속
- JPA와 연관관계
- JPA와 객체 그래프 탐색
- JPA와 비교하기
개발자가 데이터베이스에 관해 고민하지 않고 jpa.persist(album)을 날리면 JPA에서 알아서 Item과 Album을 저장하는 쿼리를 생성해준다.
조회 또한 데이터베이스에 관해 고민하지 않고 jpa.find(Album.class, albumId)를 날리면 JPA에서 알아서 Item과 Album
을 Join해서 찾아온다.
Member에 Team을 넣고 저장한 후 Member를 찾고나서 member.getTeam()을 하면 Team을 찾을 수 있다.
JPA에서 Member 객체를 가져오면 객체 그래프를 자유롭게 탐색할 수 있다.
JPA는 getTeam(), getOrder()를 해서 실제 객체를 조회해서 사용하는 시점에 SQL이 나가서 데이터를 채워주는 지연로딩이라는 기능이 있다.
때문에 JPA에서 가져오는 객체를 신뢰할 수 있게 된다.
JPA에서는 같은 Id로 조회 시 자바 객체처럼 같다고 나온다.
JPA에서는 동일한 트랜잭션에서 조회한 엔티티는 같음을 보장한다.
- 1차 캐시와 동일성(identity) 보장
- 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
- 지연 로딩(Lazy Loading)
- 같은 트랜잭션 안에서는 같은 엔티티를 반환한다. - 약간의 조회 성능 향상
- DB Isolation Level이 Read Commit이어도 애플리케이션에서 Repeatable Read 보장한다.
처음 memberId로 조회하면 JPA에서 Select 쿼리를 사용해 DB에서 Member 객체(m1)를 찾아오지만 두번째로 똑같은 memberId를 조회하면 DB가 아닌 메모리에서 Member 객체(m1)을 반환해준다. == 캐싱
- 트랜잭션을 커밋할 때까지 Insert SQL을 모은다.
- JDBC BATCH SQL 기능을 사용해서 한번에 SQL 전송한다.
- 지연 로딩 : 객체가 실제 사용될 때 로딩
jpa.find(memberId)로 Member 객체를 찾아올 때 Member 와 Team이 연관관계가 맺어져 있어도 Member 객체만 가져온다.
그 후 member.getTeam().getName() 처럼 team의 실제 데이터 값이 필요할 때 DB에서 Team 데이터를 가져온다.
- 즉시 로딩 : Join SQL로 한번에 연관된 객체까지 미리 조회
jpa.find(memberId)로 Member 객체를 찾아올 때 Member와 Team이 연관관계가 맺어져 있으면 Member와 Team을 Join해서 둘 다 가져온다.