제육's 휘발성 코딩
Published 2021. 7. 24. 16:50
[Spring JPA] JPA 란? 🔷 Spring/JPA
반응형

패러다임의 불일치

객체지향프로그래밍은 추상화, 캡슐화, 정보은닉, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공한다.

아직까지는 객체를 영구 보관하는 저장소로 여러가지 방식이 있지만, 아직까지 관계형 데이터베이스로 많이 사용한다.

즉, 객체를 SQL로 변환해야한다.

image

  • 해당 그림을 살펴보자. 객체 상속 관계로 봤을 때 Album에 데이터 저장은 Album, Item 두 곳에 모두 insert 해야한다. 저장은 어떻게든 되겠지만, 조인 연산을 통해 조회하는 경우를 생각해보자. 각각의 테이블 맞춰 객체를 생성해서 만들어야한다. 상상만해도 복잡하기 때문에 DB에 저장할 객체에는 상속 관계를 사용하지 않는다.

디비가 아닌 자바 컬렉션에서 조회 한다고 가정하면? Album album = list.get(albumId)와 같은 방식으로 사용할 수 있을 것이다.

class MemberService {
  public void process() {
        Member member = memberDAO.find(memberId);
    member.getTeam();
    member.getOrder().getDelievery();
  }
}
  • 리스트를 사용해서 구현하자니, member 객체에서 연관된 데이터들이 있는지 신뢰할 수 없다. 즉, 컴파일 시점에서 오류를 캐치할 수 없어서 해당 비즈니스로직을 일일이 확인해야한다. 즉, getMember(), getMemberWithTeam(), getMemberWithOrderWithDelievery()와 같이 메서드를 여러 개 만들어서 기능 별 필요한 객체를 로딩하도록 해야 한다.

연관 관계

image

  • 객체는 참조를 사용하기 때문에 단방향 연관 관계를 갖고 있지만, 테이블은 외래키를 사용해서 양방향으로 연관 관계를 갖고 있다.

객체답게 모델링 할수록 매핑 작업만 늘어난다. 객체를 자바 컬렉션에 저장 하듯이 DB에 저장은 하되, 원하는 객체의 로딩을 보장해줄 수 있는 방법에 대해 오랜 시간 고민해왔고, 이 문제점을 해결한 것이 바로 JPA다.

JPA 란?

  • Java Persistence API로 자바 진영의 ORM 표준 기술이다.

ORM 이란?

  • Object Relational Mapping으로 객체-관계 매핑을 해주는 표준 기술이다.
  • 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해주는 것을 말한다.
  • 객체 지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용한다.
  • ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결한다.
  • 데이터베이스 데이터 <—매핑—> Object 필드
  • 객체를 통해 간접적으로 데이터베이스 데이터를 다룬다.
  • Persistant API라고도 할 수 있다.
  • Ex) JPA, Hibernate 등

ORM 기술 과정

  • Jdbc : Datasource (import javax.sql.DataSource) 와 Connection 등을 사용하여 연결 , 예외 처리문이 많고 코드가 복잡하다.
    • 쿼리 ex) String sql = "select * from member where name = ?";
  • JdbcTemplate : JdbcTemplate (import org.springframework.jdbc.core.JdbcTemplate) 를 사용하여 기존 예외처리가 없어지고 간결해진다. 쿼리 동일
  • Jpa : EntityManager (import javax.persistence.EntityManager) 와 생성자 DI를 통해 사용하며 개발자가 생성한 Repository를 implements 하여 개발한다.
    • 쿼리 ex) List result = em.createQuery("select m from Member m where m.name = :name", Member.class)
  • Spring Data Jpa : 인터페이스로 생성 후에 JpaRepository를 추가로 JpaRepository를 extends 한다.
    • <객체클래스, 키 값> Repository -> JpaRepository에서 제공하는 CRUD를 사용하여 구현 가능하기 때문에 로직이 간단하다.

※ 실무에서는 복잡한 쿼리는 Jpa에서 제공하는 네이티브 쿼리를 사용하거나 JdbcTemplate을 혼합하여 사용한다.

JPA 동작 과정

image

  • JPA는 애플리케이션과 JDBC 사이에서 동작한다.

JPA 저장 예시

image

  • 저장은 다음과 같이 Persist를 통해 저장된 내용을 SQL로 변환하여 JDBC를 통해 쿼리를 보내서 DB에 저장한다.
  • jpa.persist() 호출 시 JPA가 직접 Insert 문을 엔티티 상태에 맞게 날려준다.

JPA 조회 예시

image

  • Entity entity = jpa.find(Entity.class, entityId); 와 같이 사용하면 JPA가 필요한 객체를 모두 로딩해서 조인 쿼리와 같은 SQL 쿼리를 만들어서 보내고 그 결과 값을 반환해준다.

JPA와 CRUD

  • 저장 : jpa.persist(member)
  • 조회 : Member member = jpa.find(memberId)
  • 수정 : member.setName()
  • 삭제 : jpa.remove(member)

JPA의 성능 최적화 기능

1차 캐시와 동일성 보장

  • 같은 트랜잭션 안에서는 같은 엔티티를 반환하는 것을 보장한다. 즉 영속성 컨텍스트에 남아있는 자료들은 디비를 거치지 않고 바로 꺼내온다. 
  • DB Isolation Level이 Read Commit이어도 애플리케이션에서 Repeatable Read를 보장한다.

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

em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
transaction.commit(); // 이 때까지 SQL을 DB에 보내지 않고 모아둔다.
  • 트랜잭션을 커밋할 때까지 INSERT SQL을 모은다.
  • JDBC BATCH SQL 기능을 사용해서 한번에 SQL 전송한다.

지연 로딩

지연 로딩과 즉시 로딩을 모두 사용할 수 있다.

  • 지연 로딩 : 객체가 실제 사용될 때 로딩하는 것
  • 즉시 로딩 : JOIN SQL로 한번에 연관된 객체까지 미리 조회 하는 것

본 포스팅은 인프런 김영한님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편'을 참고하여 정리하였습니다.

반응형
profile

제육's 휘발성 코딩

@sasca37

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요! 맞구독은 언제나 환영입니다^^