JPA 소개
- Java Persistence API
- 자바 진영의 ORM 기술 표준
ORM이란?
- Object-relational mapping (객체 관계 매핑)
- 객체는 객체대로 설계, DB는 DB대로 설계
- ORM 프레임워크가 중간에서 객체와 DB를 매핑
JPA는 애플리케이션과 JDBC 사이에서 동작
- 자바 애플리케이션에서 DB와 통신하기 위해선 JDBC API 사용이 필수
- JPA가 JDBC API를 대신 사용해줌
JPA 동작 - 저장
- DAO가 Entity를 JPA에게 던진다.
- JPA는
- Entity 분석
- INSERT SQL 생성
- JDBC API 사용
- 패러다임 불일치 해결
- JPA가 DB로 INSERT SQL을 던진다.
JPA 동작 - 조회
- DAO가 JPA에게 id를 던진다.
- JPA는
- SELECT SQL 생성
- JDBC API 사용
- ResultSet 매핑
- 패러다임 불일치 해결
- JPA가 DB로 SELECT SQL을 던진다
- DB는 결과를 반환하여 JPA에게 던진다
- JPA는 DAO에게 Entity Object를 던진다
JPA 역사
과거
EJB(엔티티 빈, 자바표준) → 너무 복잡, 성능이 떨어져서 실효성이 없었다.
→ 하이버네이트(오픈소스) 탄생
현재
하이버네이트를 정제해서 자바진영의 새로운 ORM 표준 → JPA
JPA는 표준 명세
- JPA는 인터페이스 모음
- JPA 2.1 표준 명세를 구현한 3가지 구현체
- 하이버네이트, EclipseLink, DataNucleus
JPA를 왜 사용해야 하는가?
- SQL 중심적 개발 → 객체 중심 개발
- 생산성, 유지보수
- 패러다임 불일치 해결
- 성능
- 데이터 접근 추상화와 벤더 독립성
- 표준
생산성 - JPA와 CRUD
- 저장 : jpa.persist(member)
- 조회 : Member member = jpa.find(memberId)
- 수정 : member.setName(”변경할 이름”)
- 트랜잭션 안에서, 데이터 조회 후 변경해주면 트랜잭션 끝난 시점에 자동으로 UPDATE 쿼리가 날아감
- 삭제 : jpa.remove(member)
유지보수
- 기존 : 필드 변경시 모든 SQL 수정
- JPA : 필드만 추가하면 됨, SQL은 JPA가 처리
JPA와 패러다임의 불일치 해결
JPA와 상속
- 저장
- 개발자가 할 일
jpa.persist(album);
- 나머진 JPA가 처리
INSERT INTO ITEM ...
,INSERT INTO ALBUM ...
- 개발자가 할 일
- 조회
- 개발자가 할 일
Album album = jpa.find(Album.class, albumId);
- 나머진 JPA가 처리
SELECT I.*, A.* FROM ITEM I JOIN ALBUM A ON I.ITEM_ID = A.ITEM_ID
- 개발자가 할 일
- 저장
JPA와 연관관계
연관관계 저장
member.setTeam(team);
jpa.persist(member);
JPA와 객체 그래프 탐색
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();
→ 신뢰할 수 있는 Entity, 계층
JPA와 비교하기
String memberId = "100"; Member member1 = jpa.find (Member.class, memberId); Member member2 = jpa. find (Member.class, memberId); member1 == member2; //같다.
→ 동일한 트랜잭션에서 조회한 엔티티는 같음을 보장
JPA의 성능 최적화 기능
1차 캐시와 동일성(identity) 보장
- 같은 트랜잭션 안에서는 같은 엔티티를 반환 - 약간의 조회 성능 향상
- 같은 멤버를 조회 할 때, JPA find를 실행하면 SQL 쿼리를 이용해서 DB에서 멤버를 가져온다.
- 해당 멤버를 JPA가 갖고있고, 또다시 find를 실행하면 JPA의 메모리 상에서 반환해준다.
- DB Isolation Level이 Read Commit이어도 애플리케이션에서 Repeatable Read 보장
- 같은 트랜잭션 안에서는 같은 엔티티를 반환 - 약간의 조회 성능 향상
트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
INSERT
트랜잭션을 커밋할 때까지 INSERT SQL을 모음
JDBC BATCH SQL 기능을 사용해서 한번에 SQL 전송
transaction.begin(); //[트랜잭션] 시작 em.persist(memberA); em.persist(memberB); em.persist(memberC); //여기까지 INSERT SQL을 데이터베이스에 보내지 않는다. //커밋하는 순간 데이터베이스에 INSERT SQL을 모아서 보낸다. transaction.commit(); // [트랜잭션] 커밋
지연 로딩(Lazy Loading)
지연 로딩과 즉시 로딩
지연 로딩 : 객체가 실제 사용될 때 로딩
Member member = memberDAO.find(memberId); -> SELECT * FROM MEMBER Team team = member.getTeam(); String teamName = team.getName(); -> SELECT * FROM TEAM
즉시 로딩 : JOIN SQL로 한번에 연관된 객체까지 미리 조회
Member member = memberDAO.find(memberId); -> SELECT M.*, T.* FROM MEMBER JOIN TEAM ... Team team = member.getTeam(); String teamName = team.getName();
728x90
반응형