3 minute read

JPA (Java Persistent API)

Spring JDBC(Java Database Connectivity)

  • DB에 접근(Connectivity)할 수 있도록 Java에서 제공하는 API
  • Spring JDBC는 DriveManager가 하는 일들을 JdbcTemplate에게 맡김
    • JdbcTemplate : 템플릿 메소드 패턴이 적용된 클래스이다.
  • JDBC는 DBMS 벤더에 의존하지 않고 통합된 코드를 사용하여 제어할 수 있다.

단계

  1. JDBC Driver loading (벤더에 맞는 데이터 베이스 드라이버 로딩)
  2. Connection : DB 연결
  3. Statement : SQL 구문 정의, 값 세팅
  4. executeUpdate() or executeQuery()
  5. ResultSet : 조회인 경우
  6. close : Connection, Statement, ResultSet

SQL Mapper(MyBatis), ORM

  • Mybatis는 자바 오브젝트와 SQL사이의 자동 매핑 기능을 지원하는 ORM프레임워크이다.

MyBatis

  • MyBatis에서는 프로그램에 있는 SQL 쿼리들을 별도의 파일에 구성하여 프로그램 코드와 SQL을 분리할 수 있는 장점을 가지고 있다.
  • 대부분의 JDBC 기능을 제공하며, JDBC API를 보다 간결한 코드로 편하게 사용할 수 있다. - 쿼리가 수정되면 DTO와 함께 수정해야 하는 문제 (논리적 의존관계)

ORM(Object-Relational Mapping)

  • 객체와 데이터베이스의 데이터를 자동으로 매핑.
  • 애플리케이션과 데이터베이스 사이 mapping을 통해 엔티티 클래스 객체에 포함된 정보를 테이블에 저장하는 기술이다.

JPA, Hibernate

JPA

  • 자바 ORM에 대한 API 표준 명세로, 자바 코드를 사용해서 데이터베이스에 접근이 가능하게 함
    • 구현체 예 : hibernate, EclipseLink, DataNucleus
  • 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스
    • 스프링이 제공하는 API가 아닌 자바가 제공하는 API다.
  • 스프링 부트에서는 spring-boot-starter-data-jpa로 패키지를 가져와 사용하며, Hibernate 프레임워크를 활용한다.
  • 개발자는 JPA를 활용하여 JDBC API를 통해 SQL을 호출하여 데이터베이스에 접근한다.

장점

  • 생산성
    • SQL 쿼리를 직접 생성하지 않고, JPA에 저장할 객체를 전달하고 JPA 메소드를 활용해 데이터 베이스를 다룰 수 있다.
    • SQL을 작성하고 JDBC API를 사용하는 반복적인 일을 JPA에서 대신해준다.
  • 유지보수
    • 유지 보수 측면에서 SQL의존적인 개발은 엔티티 컬럼이 변경되는 상황에서 연관된 모든 SQL문을 수정해야하고 결과를 매핑하기 위한 JDBC API도 변경해야 한다.
    • JPA는 JPA에서는 엔티티 클래스 정보만 변경하면 된다.
  • 성능 :
    • JPA는 애플리케이션과 데이터 베이스 사이에서 동작하기 때문에 다양한 성능 최적화 기회를 제공한다. 예를 들어서 같은 트랜잭션 내에서는 캐싱 기능을 제공한다.
  • 패러다임 불일치 문제 해결 :
    • 데이터 베이스는 데이터 중심으로 구조화되어있어 객체 지향 언어와 패러다임 불일치 문제가 발생한다.
    • JPA는 데이터 베이스에 맞춰 데이터를 저장하기위해 객체를 매핑하는 과정에서 드는 비용을 없애 좀 더 객체지향적인 개발이 가능하게 한다.
  • DB벤더 독립성 :
    • SQL 의존적인 개발은 DB벤더마다 문법이 다르기 때문에 다른 데이터베이스로 변경하는 작업이 어렵다.
    • JPA는 데이터베이스와 애플리케이션 사이에서 추상화 데이터 접근 계층을 제공하므로 변경 작업이 비교적 간편하다.
    • 예) 로컬 개발 환경은 H2데이터 베이스 사용, 개발이나 상용 환경은 MYSQL 사용

단점

  • JPA는 복잡한 쿼리보다는 실시간 쿼리에 최적화되어있다. 통계 처리와 같은 복잡한 작업이 필요한 경우에는 JPA가 제공하는 네이티브 SQL을 사용하거나, 기존의 Mybatis와 같은 Mapper 방식이 더 효율적일 수 있다.
  • 자동 생성되는 쿼리문이 많아 성능 최적화가 필요할 수 있다.
  • Persistent Context에서 1차 Cache, Write Behind, Dirty Checking, Lazy Loading 등의 다양한 기능을 지원해주기 때문에 해당 개념을 잘 모르고 JPA를 사용했을 경우 수 많은 예외와 성능 감소가 발생할 수 있다.

hibernate

  • JPA라는 명세의 구현체
  • JPA의 인터페이스를 구현하여 객체와 데이터베이스 간의 매핑을 처리
  • Hibernate는 SQL을 자동으로 생성하고 실행하여 데이터베이스에 대한 접근을 관리한다.

영속성 컨텍스트(Persistent Context)

  • 테이블과 매핑되는 엔티티 객체 정보를 어플리케이션 내에 오래 지속되도록 저장하는 환경이다.
  • Spring에서 EntityManager를 주입해 사용할 수 있다.

생명주기

  • 비영속(new/transient)
  • 영속성 컨텍스트 및 데이터베이스와 전혀 관계가 없는 상태
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
  • 영속(managed)
  • 영속성 컨텍스트에 저장된 상태
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(member); // 객체를 저장한 상태(영속)
  • 준영속(detached)
  • 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 실제 데이터가 삭제되지는 않지만 1차캐시부터 쓰기 지연 저장소까지 해당 엔티티를 관리하기 위한 모든 정보가 제거
em.detach(member);
  • 삭제(removed)
  • 삭제된 상태
em.remove(member);

기능

  • 1차 캐시
    • 영속성 컨텍스트 내부에 엔티티를 저장하는 캐시 메커니즘
    • 영속 상태인 엔티티에 대한 조회는 캐시에서 진행되므로 성능 향상을 가져옴
  • 변경 감지
    • 엔티티의 변경을 감지하여 자동으로 데이터베이스와 동기화
  • 지연 로딩
    • 엔티티가 실제로 필요한 시점까지 데이터베이스에서 조회하지 않는 기능으로, 성능 최적화에 도움
  • 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)

즉시 / 지연 로딩

  • 지연 로딩
    • 연관된 엔티티를 처음으로 접근할 때까지 데이터베이스 조회를 지연시킴
    • 연관된 엔티티가 실제로 필요한 시점에만 데이터베이스를 조회하므로, 불필요한 조회를 피하고 성능 최적화
    •  초기 로딩 시간이 적어지고 메모리 소비량 감소
    •  초기화가 지연되면 원하지 않는 순간 성능에 영향을 줄 수 있다.

설정

  • @ManyToOne 은 기본값이 즉시로딩이고, @OnetoMany는 지연로딩이다.
  • JPA에서 fetch = FetchType.LAZY 옵션을 지정해 설정할 수 있다.
    • 필요한 경우 fetch = FetchType.EAGER 옵션을 사용하여 즉시 로딩으로 변경 가능

주의 사항

  • 지연 로딩을 사용할 때는 영속성 컨텍스트가 엔티티를 관리하고 있는 상태여야 한다.
  • 지연 로딩을 사용하는 엔티티에 대한 접근은 영속성 컨텍스트의 범위 내에서 이루어져야 한다.
  • 지연 로딩을 사용하면서 영속성 컨텍스트 범위를 벗어나는 경우에는 예외가 발생할 수 있다.

Leave a comment