본문 바로가기
Spring/Spring JPA

JPA

by chogigang 2023. 2. 28.

JPA 맛만 보기

 

 

JPA(Java Persistence API)는 자바 ORM 기술에 대한 API 표준입니다. ORM이란 Object Relational Mapping 의 약자로

객체와 관계형 데이터베이스를 매핑해주는 것을 말합니다. 

 

우리가 일반 적으로 알고 있는 애플리케이션 Class와 RDB(Relational DataBase)의 테이블을 매핑(연결)한다는 뜻이며, 기술적으로는 어플리케이션의 객체를 RDB 테이블에 자동으로 영속화 해주는 것이라고 보면됩니다.

 

장점

  • SQL문이 아닌 Method를 통해 DB를 조작할 수 있어, 개발자는 객체 모델을 이용하여 비즈니스 로직을 구성하는데만 집중할 수 있습니다.
    (내부적으로는 쿼리를 생성하여 DB를 조작함. 하지만 개발자가 이를 신경 쓰지 않아도됩니다.)
  • Query와 같이 필요한 선언문, 할당 등의 부수적인 코드가 줄어들어, 각종 객체에 대한 코드를 별도로 작성하여 코드의 가독성을 높습니다.
  • 객체지향적인 코드 작성이 가능합니다.  오직 객체지향적 접근만 고려하면 되기때문에 생산성 증가
  • 매핑하는 정보가 Class로 명시 되었기 때문에 ERD를 보는 의존도를 낮출 수 있고 유지보수 및 리팩토링에 유리합니다.
  • 예를들어 기존 방식에서 MySQL 데이터베이스를 사용하다가 PostgreSQL로 변환한다고 가정해보면, 새로 쿼리를 짜야하는 경우가 생김. 이런 경우에 ORM을 사용한다면 쿼리를 수정할 필요가 없습니다.

 

 

단점

  • 프로젝트의 규모가 크고 복잡하여 설계가 잘못된 경우, 속도 저하 및 일관성을 무너뜨리는 문제점이 생길 수 있습니다.
  • 통계 처리 같은 복잡한 쿼리를 사용할 경우 SQL 문을 사용하는게 나을수도 있습니다. Native SQL을 통해 기존의 SQL문을 사용할 수 있지만 그러면 특정 데이터베이스에 종속된다는 단점이 생깁니다. 이를 보완하기 위해서 SQL과 유사한  JPQL을 지원합니다.
  • 학습비용이 비싸고, 학습시간이 길어집니다 관계형 DB를 충분히 알아야 JPA를 잘 사용할수 있기 때문에 관계형 db를 학습한 후 JPA를 사용하기를 권합니다.

 

JPA(Java Persistence API)
  • Java 진영에서 ORM(Object-Relational Mapping) 기술 표준으로 사용하는 인터페이스 모음
  • 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스
  • 인터페이스 이기 때문에 Hibernate, OpenJPA 등이 JPA를 구현합니다.

 

 

왜 JPA를 사용해야 할까?

JPA는 반복적인 CRUD SQL을 처리해줍니다. JPA는 매핑된 관계를 이용해서 SQL을 생성하고 실행하는데, 개발자는 어떤 SQL이 실행될지 생각만하면 되고, 예측도 쉽게 할 수 있습니다.

 

추가적으로 JPA는 네이티브 SQL이란 기능을 제공해주는데 관계 매핑이 어렵거나 성능에 대한 이슈가 우려되는 경우 SQL을 직접 작성하여 사용할 수 있습니다.

 

JPA를 사용하여 얻을 수 있는 가장 큰 것은 SQL아닌 객체 중심으로 개발할 수 있다는 것입니다.  이에 따라 당연히 생산성이 좋아지고 유지보수도 수월합니다.

 

또한 JPA는 패러다임의 불일치도해결했습니다 . 예를 들면 JAVA에서는 부모클래스 자식클래스의 관계 즉, 상속관계가 존재하는데 데이터베이스에서는 이러한 객체의 상속관계를 지원하지 않습니다.

(상속 기능을 지원하는 DB도 있지만 객체 상속과는 다름). 이런 상속관계를 JPA는 아래와 같은 방식으로 해결하였습니다.

 

출처 : 자바 ORM 표준 프로그래밍

 

 

JPA 동작 방식

 

 

엔티티

 

엔티티(Entity)란 데이터베이스의 테이블에 대응하는 클래스라고 생각하시면 됩니다.@Entity가 붙은 클래스는

JPA에서 관리하며 엔티티라고 합니다. 예를 들어 데이터베이스에 item 테이블을 만들고, 이에 대응되는 Item.java 클래스를 만들어서 @Entity 어노테이션을 붙이면 이 클래스가 엔티티가 되는 것입니다. 클래스 자체나 생성한 인스턴스도 엔티티라고 부릅니다. 

 

엔티티 매니저 팩토리

 

엔티티 매니저 팩토리는 엔티티 매니저 인스턴스를 관리하는 주체입니다. 애플리케이션 실행 시 한 개만 만들어지며 사용자로부터 요청이 오면 엔티티 매니저 팩토리부터 엔티티 매니저를 생성합니다.

 

엔티티 매니저

 

엔티티 메니저란 영속성 컨텍스트에 접근하여 엔티티에 대한 데이터베이스 작업을 제공합니다. 내부적으로 커넥션을 사용해서 데이터베이스에 접근합니다. 엔티티 매니저의 몇가지 메소드를 살펴 볼수 있습니다.

 

find() 메소드:영속성 컨텍스트에서 엔티티를 검색하고 영속성 컨텍스트에 없을 경우 데이터베이스에서 데이터를 찾아 영속성 컨텍스트에 저장합니다.

persist() 메소드:엔티티를 영속성 컨텍스트에 저장합니다.

remove() 메소드: 엔티티 클래스를 영속성 컨텍스트에서 삭제합니다.

flush() 메소드 : 영소성 컨텍스트에 저장되니 내용을 데이터베이스에 반영합니다.

 

영속성 컨텍스트

 

jpa를 이해하기 위해서는 영속성 컨텍스트를 이해하는것이 가장 중요합니다. 엔티티를 영구 저장하는 환경으로 엔티티 매니저를 통해 영속성 컨텍스트에 접근합니다.

 

엔티티 생명주기

 

 

 

 

 

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

 

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

EntityManager em = entityManagerFactory.createEntityManager();
//엔티티 매니저 팩토리로부터 엔티티 매니저를 생성합니다.
EntityTransaction transaction = em.getTransaction();
transaction.begin();
/*엔티티 매니저는 데이터 변경 시 데이터의 뭄결성을 위해 반드시 트랜잭션을 시작해야 합니다. 여기서
트랜잭션도 데이터베이스의 트랜잭션과 같은 의미로 생각하면 됩니다.*/
 

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

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

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

 

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

 

JPA는 왜 이렇게 영속성 컨텍스트를 사용하는 것일까. 바로 에플리케이션과 데이터베이스 사이에 영속성 컨텍스트라는

중간 계층을 만들었기 때문입니다. 이렇게 중간 계층을 만들면 버퍼링,캐싱 등을 할 수 있는 장점이 있습니다.

 

 

 

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문을 호출할 필요가 없습니다.

 

 

저장 

 

조회

 

 

 

'Spring > Spring JPA' 카테고리의 다른 글

Auditing을 이용한 엔티티 공통 속성 공통화  (0) 2023.03.06
영속성 전이  (0) 2023.03.06
연관 관계 매핑 종류  (1) 2023.03.05
@Query  (0) 2023.03.02
엔티티 매핑 관련 어노테이션  (0) 2023.02.28