JPA - Java Persistence API

iseon_u·2022년 7월 2일
0

JPA

목록 보기
1/6
post-thumbnail

JPA Java Persistence API


  • 자바 진영의 ORM 기술 표준

ORM Object-relational mapping

  • 객체 관계 매핑
  • 객체는 객체대로 설계
  • 관계형 데이터베이스는 관계형 데이터베이스대로 설계
  • ORM 프레임워크가 중간에서 매핑

JPA는 애플리케이션과 JDBC 사이에서 동작

  • 쿼리를 JPA 가 만들어준다.

JPA 동작 - 저장

  • 패러다임 불일치 해결

JPA 동작 - 조회

  • ResultSet 값을 객체에 매핑

JPA 표준 명세

  • 인터페이스의 모음
  • JPA 표준 명세를 구현한 구현체
  • 하이버네이트

JPA 장점

  • SQL 중심 개발 → 객체 중심 개발
  • 생산성, 유지보수, 성능, 표준

생산성 - CRUD

  • 저장: jpa.persist(member)
  • 조회: Member member = jpa.find(memberId)
  • 수정: member.setName(”변경할 이름”)
  • 삭제: jpa.remove(member)

유지보수

  • 기존: 필드 변경시 모든 SQL 수정
  • JPA: 필드만 추가하면 된다. SQL 은 JPA 가 처리

패러다임 (틀) 의 불일치 해결

JPA 와 상속

상속 - 저장

  • 개발자
    • jpa.persist(album);
  • 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); // SQL
Member member2 = jpa.find(Member.class, memberId); // 캐시
member1 == member2; // 동일하다.
  • SQL 1번만 실행

트랜잭션을 지원하는 쓰기 지연 - INSERT

  • 트랜잭션을 커밋할 때까지 INSERT SQL 을 모은다.
  • JDBC BATCH SQL 기능을 사용해서 한번에 SQL 전송
transaction.begin(); // 트랜잭션 시작
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
// 여기까지 INSERT SQL 을 데이터베이스에 보내지 않는다.
// 커밋하는 순간 데이터베이스에 INSERT SQL 을 모아서 보낸다.
transaction.commit(); // 트랜잭션 커밋

지연 로딩과 즉시 로딩

  • JPA 에서 옵션에 따라 선택 가능
// 지연 로딩
Member member = memberDAO.find(memberId); // SELECT * FROM MEMBER
Team team = member.getTeam();
String teamName = team.getName();  // SELECT * FROM TEAM
  • 지연 로딩: 객체가 실제 사용될 때 로딩
// 즉시 로딩
Member member = memberDAO.find(memberId); // SELECT M.*, T.*
Team team = member.getTeam();             // FROM MEMBER
String teamName = team.getName();         // JOIN TEAM ...
  • 즉시 로딩: JOIN SQL 로 한번에 연관된 객체끼리 미리 조회
profile
🧑🏻‍💻 Hello World!

0개의 댓글