Backend/JPA

[JPA]JPA를 왜 사용해야 하는가?

GAEBAL 2022. 7. 22. 15:05
728x90

JPA를 왜 사용해야 하는가?

  • SQL 중심적인 개발에서 객체 중심으로 개발
  • 생산성
  • 유지보수
  • 패러다임의 불일치 해결
  • 성능
  • 데이터 접근 추상화와 벤더 독립성
  • 표준

 

 

 

생산성

  • 저장
  • jpa.persist(member)
  • 조회
  • Member member = jpa.find(memberId)
  • 수정 -> 개꿀
  • member.setName("변경할 이름")
  • 삭제
  • jpa.remove(member)

 

 

 

유지보수

  • 기존
    • 필드 변경 시 모든 SQL 수정
  • JPA
    • 필드만 추가하면 됨, SQL은 JPA가 처리

 

 

 

JPA와 패러다임의 불일치 해결

(관계형 데이터베이스(RDBMS)와 객체의 패러다임의 불일치 해결)

 

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();
  • .find()로 가져온 객체는 신뢰할 수 있음 !
  • 자유로운 객체 그래프 탐색 가능 !

 

JPA와 비교하기

  • String memberId = "100";
    Member member1 = jpa.find(Member.class, memberId);
    Member member2 = jpa.find(Member.class, memberId);
    member1 == member2; // 같다
  • 동일한 트랜잭션에서 조회한 엔티티는 같음을 보장 !

 

 

 

JPA의 성능 최적화 기능

  1. 1차 캐시와 동일성(identity) 보장
  2. 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
  3. 지연 로딩(Lazy Loading)

 

1차 캐시와 동일성 보장

  1. 같은 트랜잭션 안에서는 같은 엔티티를 반환 - 약간의 조회 성능 향상SQL 한번만 실행 !
  2. String memberId = "100"; Member member1 = jpa.find(Member.class, memberId); // SQL Member member2 = jpa.find(Member.class, memberId); // 캐시 println(member1 == member2); // true
  3. DB Isolation Level이 Read Commit이어도 애플리케이션에서 Repeatable Read 보장

 

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

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

 

지연 로딩과 즉시 로딩

  • 지연 로딩: 객체가 실제 사용될 때 로딩
  • 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