Jpa/series

[jpa 1편] jpa 개념 정리

무대포 개발자 2022. 6. 16. 22:50
728x90
반응형

목차는 jpa series 목차 에 있습니다.

[Jpa 1편] jpa 개념 정리

Jpa 란?

  • Java Persistence API 약자입니다.
  • 자바 ORM 기술에 대한 API 표준 명세 입니다.
  • ORM 사용을 위한 인터페이스를 모아둔 것 입니다.

ORM 이란?

  • Object Releational Mapping 으로서 객체와 관계형 데이터베이스 맵핑을 의미합니다.
  • 패러다임의 불일치 문제 및 SQL 생성을 해주며, Object 와 RDB 를 맵핑해줌으로써 기존의 DB 접근 방식에 대한 개선된 점이 있습니다.

Jpa 장점

  • 코드 간결성 및 반복되는 작업 감소
    • 예시는 다음과 같습니다. JDBC 를 이용해서 insert, update 를 한다고 가정합니다.
    • update, insert 를 개발했는데 update, insert 에 컬럼을 추가하는 요구사항이 발생했습니다.
    • 기존 방식대로라면 update, insert 에 사용되는 객체에 컬럼을 추가하고, update, insert 에 사용되는 쿼리에 컬럼을 추가해줘야 합니다.
    • Jpa 는 Entity 만 수정하면 내부 프레임워크에서 처리해줍니다.
  • 코드 명확함
    • SQL Query 을 보는 것보다 코드만 보고 어떻게 동작할지 쉽게 짐작이 갑니다.
    • 물론 복잡한 쿼리는 (조인문이 많은) 코드나 SQL query 나 둘 다 복잡하겠지만 간단한 것들은 코드 보기가 쉽습니다.

Jpa 단점

  • learning cost 높습니다.
    • jpa 구조를 모르면 예상치 못하게 동작합니다.(n+1, osiv 등)

Jpa 특징

  • 운영 및 추가 개발이 편리합니다. (코드를 보고 분석할 수 있으니 SQL 을 보는 것보다 resource 가 덜 들어갑니다.)
  • 패러다임 불일치 해결합니다. (아래에서 자세히 설명합니다.)
  • 성능
    • JDBC 와 프로그램 간 중간에 JPA 가 위치하고 있기에 이 이점을 이용해 성능 개선 가능합니다. (늦게 쓰기)

패러다임 불일치 해결

  • 패러다임 불일치란 다음과 같습니다.
  • SQL 에 종속적인 프로그램 코드를 객체지향적 프로그래밍에서 SQL 을 표현하고 제어하고 싶어하는 요구사항이 있습니다.
  • 이러한 것을 해결하기 위해 JPA 가 나왔고, 객체지향적 프로그래밍을 통해 SQL 을 표현하고 제어할 때, 몇 가지 문제점이 나왔는데 그것을 패러다임 불일치 문제라고 합니다.

패러다임 불일치 - 상속

  • 객체는 상속이 가능하지만, 관계형 데이터베이스는 상속이 없습니다.
  • 그렇기에 상속 관계의 객체를 관계형 데이터베이스에 집어넣기 위해서는 각각의 객체를 가져와 테이블에 넣어줘야 합니다.
INSERT INTO PARENT(xxx) ;
INSERT INTO CHILD(xxx) ;
  • 이러한 이유는 객체와 RDB 가 사용하는 용도가 다르기 때문입니다. 객체 지향 언어는 객체 간의 통신을 통해 현실세계의 복잡함을 푸는 언어고, 상속, 추상화, 다형성을 통해 구현합니다.
  • 그에 비해 RDB 는 테이블 간의 관계(join 등) 를 통해 처리하는 구조입니다. 이러한 용도와 목적의 차이를 패러다임의 불일치라고 하고, 불편함이 발생합니다.
  • Jpa 에서는 위와 같은 것을 해결하기 위해 다음과 같이 처리합니다.
public class Parent {
    Child child;

    ...
    ...
}

jpa.persist(parent);
  • 위와 같이 하면 저 위에 것처럼 쿼리를 여러 번 날릴 필요 없이 Jpa 내부에서 자동으로 처리해줍니다.
  • 즉, 상속의 경우 객체 안에 객체를 정의해놓음으로써 JPA 가 자동으로 이를 연결시켜줍니다.

패러다임 불일치 - 연관 관계

  • 객체는 참조를 통해 연관된 객체를 조회합니다.
  • 반면 RDB 테이블은 외래키를 사용해서 테이블 간 연관관계를 맺습니다.
  • 이러한 구조로 인해 발생되는 문제점은 다음과 같습니다.
public class Parent {
    Child child;

    public Child getChild() {
      return child;
    }
}

// 위와 같을 때, Parent 를 가지고 저장할려면, Child 의 key 를 가져와야 한다.
// 가져온 Child key 를 가지고, 테이블에 저장을 해야합니다.
parent.getChild().getId();
insert (parent xxx);
insert (child xxx);

// Jpa 에서는 다음과 같이 처리합니다.
// 자동으로 연관관계를 맺어 처리해줍니다.
parent.setChild(child);
jpa.persist(parent);
  • 이런 문제를 해결하기 위해 JPA 에서는 객체를 참조할 때 자동으로 외래키를 조회해서 다른 객체를 조회해옵니다.
    • get method 를 사용하는 것만으로 JPA 가 알아서 SQL 을 생성해서 데이터를 조회한다.

패러다임 불일치 - 객체 그래프 탐색

  • 객체의 참조를 통해 계속해서 탐색하는 것을 의미합니다.
  • 객체만으로는 객체 그래프 탐색이 어디까지 이루어질 수 있는지 알 수 없습니다. 확인할려면 SQL 을 직접 확인해서 어떤 데이터를 조회하는지를 알아야 합니다.
    • 즉, SQL 를 통해 어떤 데이터 들을 가져올지를 결정해야 합니다.
  • JPA는 해당 문제를 지연로딩으로 해결했습니다. 참조되는 객체를 실제로 호출할 때, 해당 데이터를 읽어오는 것입니다.
    • SQL 을 통해 어떤 객체들을 조회할지 결정하는게 아니라 Entity 에서 getXxx() 하는 것으로 객체 그래프를 어떻게 탐색할지 결정 가능합니다.
    • 이렇게 함으로써 불필요한 resource 소모도 막을 수 있습니다.

패러다임 불일치 - 비교

  • RDB 는 기본키의 값으로 로우를 비교합니다.
  • 객체는 '==', 'equals' 사용합니다. (== 주소 비교, equals 값 비교)
  • 이런 패러다임의 문제를 해결하기 위해 JPA 는 같은 트랜잭션일 때, 같은 키로 조회하면 같은 객체가 조회되는 것을 보장합니다. (같은 객체 = 같은 인스턴스)

jpa lifecycle

비영속

  • Persistence Context 에서 관리하지 않는 상태입니다.

영속

  • Persistence Context 에서 관리하는 상태입니다.
  • find 를 통해 데이터를 검색했거나, persist 메소드를 통해 저장한 경우 영속성 상태가 됩니다.

삭제

  • 관리되고 있는 객체를 removed & flush 메소드를 통해 삭제했을 때, 실제 DB 에 삭제가 됩니다. (이 상태가 삭제 상태입니다.)

준영속

  • 영속성 상태에 있던 Entity 가 분리된 상태입니다. 즉, DB 와 더 이상 동기화 하지 않습니다.
  • 준영속상태로 만드는 방법은 다음과 같습니다.
    • em.detach(entity) : 특정 엔티티만 준영속 상태로 전환합니다.
    • em.clear() : 영속성 컨텍스트를 완전히 초기화합니다.
    • em.close() : 영속성 컨텍스트를 종료합니다.

Jpa 와 MyBatis 비교

  • Jpa 는 객체와 관계형 데이터베이스 간 맵핑을 해주는 개념이며, MyBatis 는 SQL 맵퍼이며, 객체와 SQL 과의 맵핑을 담당합니다.
  • MyBatis 의 장점은 명확합니다. SQL 코드를 직접 작성해 데이터를 가져와서 객체와 맵핑을 시켜줍니다.
    • 복잡한 쿼리일수록 MyBatis 가 편할 때가 있습니다.

Reference

  • 자바 ORM 표준 JPA 프로그래밍 책 참고