mojo's Blog

JPA 이란 본문

JPA

JPA 이란

_mojo_ 2022. 8. 1. 00:24

JPA

 

- Java Persistence API

- 자바 진영의 ORM 기술 표준이다.

 

ORM 

 

- Object-relational mapping (객체 관계 매핑)

- 객체는 객체대로 설계

- 관계형 데이터베이스는 관계형 데이터베이스대로 설계

- ORM 프레임워크가 중간에서 매핑

 

 JPA는 표준 명세

 

- JPA 는 인터페이스의 모음

- JPA 2.1 표준 명세를 구현한 3가지 구현체

- 하이버네이트, EclipseLink, DataNucleus

 

 

 JPA를 사용하는 이유

 

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

 

① 생산성 (JPA 와 CRUD)

 

- 저장 : jpa.persist(member)

- 조회 : Member member = jpa.find(memberId)

- 수정 : member.setName("변경이름")

- 삭제 : jpa.remove(member)

 

CRUD 를 보면 미리 코드가 만들어져서 간단하게 활용만 하면 된다!

 

 

② 유지보수 (기존 : 필드 변경시 모든 SQL 수정)

public class Member {
    private String memberId;
    private String name;
    private String tel;
    ...
}

 

Member 클래스에서 tel 이라는 String 타입 필드가 추가되었다고 하자.

그렇다면 모든 SQL 을 tel 이 추가되었다는 이유만으로 수정을 해줘야 한다.

 

- INSERT INTO MEMBER(MEMBER_ID, NAME, TEL) VALUES

- SELECT MEMBER_ID, NAME, TEL FROM MEMBER M

- UPDATE MEMBER SET ... TEL = ?

- ...

 

JPA 를 사용하게 된다면?

 => 필드만 추가하면 되며, SQL 은 JPA 가 알아서 처리해준다!

 

 

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

 

1. JPA 와 상속

2. JPA 와 연관관계

3. JPA 와 객체 그래프 탐색

4. JPA  와 비교하기

 

 

1. JPA 와 상속

 

 

왼쪽은 객체 상속 관계, 오른쪽은 Table 슈퍼타입 서브타입 관계이다.

 

앨범 정보를 저장하고 싶을 때, 다음과 같이 코드를 작성하면 끝이다.

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 )

 

 

2. JPA 와 연관관계

 

JPA 와 연관관계, 객체 그래프 탐색에 대해 알아보도록 한다.

우선 연관관계 저장은 다음과 같이 이뤄진다.

member.setTeam(team);
jpa.persist(member);

 

Member 클래스를 상속한 Team 클래스가 있으며 member 는 team 을 참조하기 때문에 setTeam() 을 해준다.

그리고 참조가 완료되면 저장을 수행한다.

 

 

3. JPA 와 객체 그래프 탐색

 

객체 그래프 탐색은 다음과 같이 이뤄진다.

Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();

 

우선 멤버 클래스로 memberId 를 통해서 member 객체를 받아온다.

그런데 member.getTeam() 을 하면 team 을 받아올 수 있는데 이는 find 과정에서 참조까지 고려하여

객체를 생성한 것으로 볼 수 있다. (마치 컬렉션에 넣었던 것처럼)

 

 

4. JPA  와 비교하기

String memberId = "100";
Member member1 = jpa.find(Member.class, memberId);
Member member2 = jpa.find(Member.class, memberId);

member1 == member2; // same!

 

동일한 트랜잭션에서 조회한 엔티티는 같음을 보장한다.

 

 

 JPA의 성능 최적화 기능

 

1. 1차 캐시와 동일성(identity) 보장

2. 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)

3. 지연 로딩(Lazy Loading)

 

 

① 1차 캐시와 동일성 보장

 

1. 같은 트랜잭션 안에서는 같은 엔티티를 반환한다. - 약간의 조회 성능을 향상

2. DB Isolation Level 이 Read Commit 이어도 애플리케이션에서 Repeatable Read 보장

 

String memberId = "100";
Member member1 = jpa.find(Member.class, memberId); // SQL
Member member2 = jpa.find(Member.class, memberId); // Cache

println(member1 == member2) // true

 

동일한 트랜잭션에서 조회할 때 엔티티는 같다는 것을 위에서 확인하였다.

즉, 동일한 트랜잭션에서 한번 더 조회할 때 캐시 작업이 이뤄져서 SQL 이 1번만 실행된다.

(약간의 조회 성능이 향상됨)

 

 

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

 

1. 트랜잭션을 커밋할 때까지 INSERT SQL 을 모음

2. JDBC BATCH SQL 기능을 사용해서 한번에 SQL 을 전송

 

transaction.begin(); // [트랜잭션] 시작

em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
// 여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.

// 커밋하는 순간 데이터베이스에 INSERT SQL을 모아서 보낸다.
transaction.commit(); // [트랜잭션] 커밋

 

처음에 트랜잭션 시작을 통해 이뤄진다.

em.persist() 에서 memberA, memberB, memberC 에 대한 INSERT SQL 을 모은다.

INSERT SQL 을 모았으면 데이터베이스에 커밋하는 순간에 보낸다.

 

 

③ 지연 로딩과 즉시 로딩

 

- 지연 로딩 : 객체가 실제 사용될 때 로딩

- 즉시 로딩 : JOIN SQL 로 한번에 연관된 객체까지 미리 조회

 

지연 로딩

Member member = memberDAO.find(memberId); // SELECT * FROM MEMBER
Team team = member.getTeam(); 
String teamName = team.getName(); // SELECT * FROM TEAM

 

member 객체를 가져올 때 SELECT * FROM MEMBER 만 수행이 된다.

그리고 member.getTeam() 을 통해 team 객체를 가져오고 team.getName() 을 하는 순간,

그 시점에 SELECT * FROM TEAM 을 수행함으로써 실제 사용될 때 로딩이 되는 것을 알 수 있다.

 

즉시 로딩

Member member = memberDAO.find(memberId); // SELECT M.*, T.* FROM MEMBER JOIN TEAM ...
Team team = member.getTeam();
String teamName = team.getName();

 

위 방식은 한방에 team 까지 같이 가져오며 즉시 로딩되는 것을 알 수 있다.

 

'JPA' 카테고리의 다른 글

다양한 연관관계 매핑  (0) 2022.08.10
연관관계 매핑 기초  (0) 2022.08.10
엔티티 매핑  (0) 2022.08.09
영속성 관리 - 내부 동작 방식  (0) 2022.08.08
JPA 시작  (0) 2022.08.01
Comments