JPA?

2023. 6. 1. 00:09

✔️ 패러다임의 불일치 : 객체와 관계형 DB의 차이 

  • 객체는 추상화, 상속, 다형성(클래스, 메서드)의 특징을 가지고 RDB(Relational DataBase)는 데이터 중심으로 이루어져 RDB에 객체를 저장하는 데 불일치 발생
  • 직접 저장하거나 조회할 수 없기 때문에 객체지향 애플리케이션과 데이터베이스 중간에서  SQL과  JDBC API를 사용해서 변환 작업을 직업 해주어야 함 
  • 상속 : 객체랑은 다르게 상속이라는 기능 없음 -> 개발자가 여러 설정/ 쿼리를 생성해야 해
    => JPA에서는 여러 쿼리를 한번에 실행해서 해결!
  • 연관 관계 :  객체는 참조를 사용해서 연관된 객체 조회, 테이블은 외래키로 연관 관계를 설정하고 조인으로 연관 테이블 조회 
  • 객체 그래프 탐색 : 어디까지 탐색할 수 있는지는 실행하는 SQL에 따라 정해짐 -> 엔티티가 SQL에 논리적으로 종속되어서 발생
    하지만 JPA는 실제 객체를 사용시점까지 DB 조회를 미룬다(지연 로딩) 즉 연관된 객체를 신뢰하고 조회할 수 있음 
  • 비교 : 데이터베이스는 기본 키의 값으로 각 로우 구분, 객체는 동일성 비교와 동등성 비교 
    • 동일성 비교 ==, 객체 인스턴스의 주소 값을 비교
    • 동등성 비교 equals() 메서드, 객체 내부의 값 비교 
      => JPA는 같은 트랜잭션일 때 같은 객체가 조회되는 것을 보장함

✔️ SQL 중심 개발 
→ 같은 코드의 무한 반복 (SQL코드, 기본  CRUD의 반복)

  • 객체를 데이터베이스에 CRUD하려면 많은 SQL과 JDBC API를 코드로 작성해야함 
  • 강한 의존관계 

 

💡 JPA란?

➡️ JPA 사용하면 객체를 데이터베이스에 저장하고 관리할 때 개발자가 직접  SQL을 작성하는 것이 아니라 JPA가 제공하는 API 사용하면 됨 그러면 JPA가 개발자 대신에 적절한 SQL 생성해서 데이터베이스에 전달 

(상품 엔티티만 만들고 쿼리메서드 돌리면 원하는 SQL 생성해줌) -> find()

➡️ 자바의 ORM 기술 표준 

➡️  Java Persistence API, 자바 애플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스 

➡️ 하이버네이트를 기반으로 새로운 자바 ORM 기술 표준을 만든 것 : JPA

ORM(Object-Relational Mapping)
: 객체와 관계형 데이터베이스를 매핑한다는 뜻 
ORM 프레임워크는 객체와 테이블을 매핑해서 패러다임의 불일치 문제를 개발자 대신 해결해줌
Hibernate(하이버네이트)
: JPA 구현체의 한 종류 (다른 구현체도 있지만 가장 대중적)

 

🔎 장점 

  1. 특정 데이터베이스에 종속되지 않음
  2. 객체지향적 프로그래밍
  3. 생산성 향상
  4. 유지보수

🔎 단점

  1. 복잡한 쿼리 처리 
    : 통계 처리 같은 복잡한 쿼리를 사용할 경우는 SQL문을 사용하는 게 나을 수도 있음
    JPA는 실시간 처리용 쿼리에 더 최적화되어 있음 
  2. 성능 저하 위험 
    : 객체 간의 매핑 설계를 잘못했을 때 성능 저하 발생할 수 있음
  3. 학습 시간 
    : JPA를 제대로 사용하려면 알아야 할 것이 많아 학습하는 데 시간이 오래 걸림 

 

💡 JPA 동작 방식

✔️ 엔티티

➡️ 데이터베이스의 테이블에 대응하는 클래스 

➡️ @Entity 어노테이션이 붙은 클래스를 JPA가 관리

 

✔️ 엔티티 매니저 팩토리(Entity Manager Factory)

➡️ 엔티티 매니저 인스턴스를 관리하는 주체 

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

 

✔️ 엔티티 매니저(Entity Manager)

➡️ 영속성 컨텍스트(Persistence Context)에 접근하여 DB 작업을 제공하는 객체

➡️ 데이터베이스 커넥션을 사용해서 데이터베이스에 접근

  • find()
    : 영속성 컨텍스트에서 엔티티를 검색하고 영속성 컨텍스트에 없을 경우 데이터베이스에서 데이터를 찾아 영속성 컨텍스트에 저장
  • persist() : 엔티티를 영속성 컨텍스트에 저장
  • remove() : 엔티티 클래스를 영속성 컨텍스트에서 삭제
  • flush() : 영속성 컨텍스트에 저장된 내용을 데이터베이스에 반영

 

💡 영속성 컨텍스트(Persistence Context)

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

  • new(비영속) : new 키워드를 통해 생성된 상태로 영속성 컨텍스트와 관련이 없는 상태
  • managed(영속) : 엔티티가 영속성 컨텍스트에 저장된 상태로 영속성 컨텍스트에 의해 관리되는 상태 영속 상태에서 데이터베이스에 저장되지 않으며 트랜잭션 커밋 시점에 데이터베이스에 반영
  • detached(준영속 상태) : 영속성 컨텍스트에 엔티티가 저장되었다가 분리된 상태
  • removed(삭제 상태) : 영속성 컨텍스트와 데이터베이스에서 삭제된 상태
// 1. 영속성 컨텍스트에 저장할 상품 엔티티 생성, 
// new 키워드를 통해 생성했으므로 영속성 컨텍스트와 관련이 없는 상태
Item item = new Item();
item.setItemNm("테스트 상품");

// 2. 엔티티 매니저 팩토리로부터 엔티티 매니저 생성
EntityManager em = entityManagerFactory.createEntityManager();


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

// 4. 생성한 상품 엔티티가 영속성 컨텍스트에 저장된 상태,
// 아직 데이터베이스에 INSERT SQL 보내지 않은 단계
em.persistance(item);

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

// 6,7. 엔티티 매니저와 엔티티 매니저 팩토리의 close() 메소드 호출해 자원 반환
em.close();
emf.close();

 

 

🔎 영속성 컨텍스트 이점

  • 1차 캐시 : 영속성 컨텍스트는 1차 캐시가 존재하며 Map<KEY, VALUE>로 저장됨 entityManager.find( ) 메소드 호출 시 영속성 컨텍스트의 1차 캐시 조회 엔티티가 존재할 경우 해당 엔티티 반환, 없을 경우 DB에서 조회 후 1차 캐시에 저장 및 반환
  • 동일성 보장 : 하나의 트랜잭션에서 같은 키값으로 영속성 컨텍스트에 저장된 엔티티 조회 시 같은 엔티티 조회 보장 → 1차 캐시에 저장된 엔티티를 조회하기 때문에 가능
  • 트랜잭션을 지원하는 쓰기 지연 : 영속성 컨텍스트에는 쓰기 지연 SQL 저장소가 존재, entity.Manager.persist( )를 호출하면 1차 캐시에 저장되는 것과 동시에 쓰기 지연 SQL 저장소에 SQL 저장됨 SQL 쌓아두고 트랜잭션을 커밋하는 시점에 저장된 SQL문들이 flush 되면서 데이터베이스에 반영 → 모아서 보내기 때문에 성능에서 이점 볼 수 있음
  • 변경 감지 : JPA는 1차 캐시의 데이터베이스에 처음 불러온 엔티티의 스냅샷 값을 갖고 있음 1차 캐시에 저장된 엔티티와 스냅샷을 비교 후 변경 내용이 있다면 UPDATE SQL문을 쓰기 지연 SQL저장소에 담아둠 그 다음 데이터베이스에 커밋 시점에 변경 내용을 자동으로 반영 → 따로 update문을 호출할 필요 없음

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

@Query 어노테이션  (0) 2023.08.15
기본키(Primary Key) 매핑 - @Id, @GeneratedValue  (0) 2023.07.29
쿼리 메서드(Query Method)  (0) 2023.06.28

BELATED ARTICLES

more