본문 바로가기
자바/JPA

[Java/JPA] JPA 개념

by drCode 2021. 10. 15.
728x90
반응형
728x90

JPA(Java Persistence API')는 자바 ORM 기술에 대한 API 표준이다.

ORM이란, 'Object Relational Mapping'의 약자로 객체와 관계형 데이터베이스를 매핑해주는 것을 말한다.

 

ORM 기술이 등장한 계기는?

1) 개발자가 SQL을 매핑하는 역할을 반복해야함

  : 자바 객체를 SQL을 통해 데이터베이스에 관리하게 하고, 데이터베이스에 저장된 데이터를 자바 애플리케이션에서 사용하려면 SQL을 통해 다시 자바 객체로 변환하는 반복적인 작업

 

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

  : 자바는 객체지향 패러다임, 관계형 데이터베이스는 데이터를 정규화해서 잘 보관하는 것을 목표로 함.

  : 객체를 DB에 넣기 위해서는 SQL 문을 통해 변환해서 저장, 데이터베이스에서 객체를 가져오기 위해서는 SQL문을 통해 변환해야함.

 

※ 객체를 단순히 데이터 전달 목적으로 사용할 뿐 객체지향적으로 프로그래밍을 할 수는 없다.

 

ORM은 객체와 데이터베이스를 매핑해주는 역할을 함.

 

ORM을 이용한 자바 객체와 관계형 데이터베이스 매핑

 

ORM의 등장의 결과로, 개발자들이 소스를 조금 더 객체지향적으로 설계하고 비즈니스 로직에 집중할 수 있게 됌

 

JPA는 ORM 기술의 표준 명세로 자바에서 제공하는 API이다.

즉, JPA는 인터페이스이고, 대표적인 구현체로 Hibernate, EclipseLink, DataNucleus, OpenJpa, TopLink 등이 있다.

 

JPA 인터페이스를 구현한 가장 대표적인 오픈소스가 Hibernate(하이버네이트)이다.

 

실질적인 기능은 Hibernate에 구현되어 있다.

 

반응형

JPA 사용 시 장점

1) 특정 데이터베이스에 종속되지 않음

  : Oracle -> MariaDB로 바꾸는데 쿼리문마다 수정을 신경쓰지 않아도 됌

  : JPA는 추상화한 데이터 접근 계층을 제공한다. 설정 파일에 어떤 데이터베이스를 사용하는지 알려주면 얼마든지 데이터베이스를 변경할 수 있다.

 

2) 객체지향적 프로그래밍

  : JPA 사용 시 데이터베이 설계 중심의 패러다임 -> 객체지향적 설계 가능

 

3) 생산성 향상

  : DB 테이블에 새로운 컬럼이 추가되었을 경우, 해당 테이블의 컬럼을 사용하는 DTO 클래스의 필드도 모두 변경해야하지만, JPA는 테이블과 매핑된 클래스에 필드만 추가한다면 쉽게 관리가 가능하다.

  : SQL문을 직접 작성하지 않고 객체를 사용하여 동작함 -> 유지보수 측면에서도 좋고 재사용성이 증가

 

JPA 사용 시 단점

1) 복잡한 쿼리 처리

  : 통계같은 복잡한 쿼리는 JPA보다는 SQL문을 사용하는게 나을수도 있다.

  : JPA에서는 Native SQL을 통해 기존 SQL문을 사용할 수 있지만, 특정 데이터베이스에 종속된다는 단점이 생긴다.

  => 이를 보완하기 위해 JPQL이 등장함.

 

2) 성능 저하 위험

  : 객체 간의 매핑 설계를 잘못했을 때, 성능 저하가 발생할 수 있으며, 자동으로 생성되는 쿼리가 많기 때문에 개발자가 의도치 않은 쿼리로 인해 성능 저하 유발됌

 

3) 학습 시간

  : 학습 시 오랜 시간이 걸림

  : 보통은 관계형 DB를 충분히 알아야 JPA를 잘 사용할 수 있음

 

JPA 동작 방식

JPA 동작 방식

엔티티

 : DB의 테이블에 대응하는 클래스.

 : @Entity가 붙은 클래스는 JPA에서 관리하며 엔티티라고 함

 : 클래스 자체나 생성한 인스턴스도 엔티티라고 부른다.

 

영속성 컨텍스트

 : 엔티티를 영구 저장하는 환경으로 엔티티 매니저를 통해 영속성 컨텍스트에 접근함

 

앤티티 매니저

 : 영속성 컨텍스트에 접근하여 엔티티에 대한 데이터베이스 작업을 제공한다.

 : 내부적으로 데이터베이스 커넥션을 사용해서 데이터베이스에 접근함

  1) find()     : 영속성 컨텍스트에서 엔티티를 검색하고 영속성 컨텍스트에 없을 경우 데이터베이스에서 데이터를 찾아 영속성 컨텍스트에 저장함

  2) persist()  : 엔티티를 영속성 컨텍스트에 저장함

  3) remove() : 엔티티 클래스를 영속성 컨텍스트에서 삭제함

  4) flush()    : 영속성 컨텍스트에 저장된 내용을 데이터베이스에 반영함

 

 

엔티티 매니저 팩토리

 : 엔티티 매니저 인스턴스를 관리하는 주체.

 : 애플리케이션 실행 시 한 개만 만들어지며 사용자로부터 요청이 오면 엔티티 매니저 팩토리로부터 앤티티 매니저를 생성함

 

엔티티 생명주기

엔티티 생명주기

생명주기 내용
비영속(new) new 키워드를 통해 생성된 상태로 영속성 컨텍스트와 관련이 없는 상태
영속(managed) - 엔티티가 영속성 컨텍스트에 저장된 상태로 영속성 컨텍스트에 의해 관리되는 상태
- 영속 상태에서 데이터베이스에 저장되지 않으며, 트랜잭션 커밋 시점에 데이터베이스에 반영
준영속 상태(detached) 영속성 컨텍스트에 엔티티가 저장되었다가 분리된 상태
삭제 상태(removed) 영속성 컨텍스트와 데이터베이스에서 삭제된 상태

 

Item item = new Item();
// 영속성 컨텍스트에 저장할 상품 엔티티를 하나 생성한다
// new 키워드를 통해 생성했으므로, 영속성 컨텍스트와 관련이 없는 상태이다.

item.setItemNm("테스트 상품");

EntityManager em = entitiyManagerFactory.createEntityManager();
// 엔티티 매니저는 팩토리롤부터 엔티티 매니저를 생성한다.

EntityTransaction transaction = em.getTransaction();
// 엔티티 매니저는 데이터 변경 시 데이터의 무결성을 위해 반드시 트랜잭션을 시작해야 한다.
// 여기서의 트랜잭션도 데이터베이스의 트랜잭션과 같은 의미로 생각하면 된다.

transaction.begin();

em.persiste(item);
// 생성한 상품 엔티티가 영속성 컨텍스트에 저장된 상태이다. 여기까지는 INSERT SQL을 보내지 않은 단계이다.

transaction.commit();
// 트랜잭션을 데이터베이스에 반영한다.
// 이때 영속성 컨텍스트에 저장된 상품 정보가 데이터베이스 INSERT 되면서 반영된다.

em.close();
emf.close();
// 엔티티 매니저와 엔티티 매니저 팩토리의 close() 메소드를 호출해 사용한 자원을 반환한다.

 

영속성 컨텍스트 사용 시 이점

JPA가 영속성 컨텍스트를 사용하는 이유는 애플리케이션과 데이터베이스 사이에 영속성 컨텍스트라는 중간 계층을 만들었기 때문이다.

이렇게 중간 계층을 만들면 버퍼링, 캐싱 등을 할 수 있는 장점이 있다.

 

영속성 컨텍스트 1차 캐시 구조

 

1차 캐시

 : 영속성 컨텍스트에는 1차 캐시가 존재하며, Map<Key, Value>로 저장됌

 : entityManager, find() 메소드 호출 시 영속성 컨텍스트의 1차 캐시를 조회함

 : 엔티티가 존재할 경우 해당 엔티티를 반환하고, 엔티티가 없으면 데이터베이스에서 조회 후 1차 캐시에 저장 및 반환

 

동일성 보장

 : 하나의 트랜잭션에서 같은 키값으로 영속성 컨텍스트에 저장된 엔티티 조회 시 같은 엔티티 조회를 보장함

 : 바로 1차 캐시에 저장된 엔티티를 조회하기 때문에 가능함

 

영속성 컨텍스트 쓰기 지연 SQL 저장소

 

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

 : 영속성 컨텍스트에는 쓰기 지연 SQL 저장소가 존재한다.

 : entityManager.persist()를 호출하면 1차 캐시에 저장되는 것과 동시에 쓰기 지연 SQL 저장소에 SQL문이 저장된다.

 : SQL을 쌓아두고 트랜잭션을 커밋하는 시점에 저장된 SQL문들이 flush 되면서 데이터베이스에 반영된다,

 : 이렇게 모아서 보내기 때문에 성능에서 이점을 볼 수 있다.

 

변경 감지

 : JPA는 1차 캐시에 데이터베이스에서 처음 불러온 엔티티의 스냅샷을 갖고 있다.

 : 1차 캐시에 저장된 엔티티와 스냅샷을 비교 후 변경 내용이 있다면 UPDATE SQL 문을 쓰기 지연 SQL 저장소에 담아둔다.

 : 데이터베이스 커밋 시점에 변경 내용을 자동으로 반영한다. 즉, 따로 update 문을 호출할 필요가 없다.

 

 

728x90
반응형

댓글