jpa 특징

이태형·2024년 12월 18일

Growth Log

목록 보기
7/18

사용

  • 실시간 데이터 처리에 적합
  • 통계, 분석과 같은 쿼리에는 부적합 - myBatis 같은 실제 쿼리를 사용하는 것으로 해야 함

사용 이유

  • SQL 에 의존적인 개발을 피하기 위함
    • JPA 를 사용하지 않는 경우, 테이블이 변경되면 쿼리문 자체를 변경해줘야 함
    • 테이블에 매핑된 객체를 신뢰할 수 없음, 객체와 쿼리문 두 곳을 DB와 비교해줘야 함
  • JAVA 문법과 비슷하게 DB를 관리할 수 있음
    • 여러 값을 저장할 때, List 와 같은 컬렉션을 지원하여, List 에 담고 저장하면 됨
  • 패러다임에 불일치
    • 관계형 데이터베이스는 테이블에 외래키를 사용하여 다른 테이블과 연관관계를 맺지만, 객체지향 모델링에서는 외래키가 존재하지 않아, 연관된 객체의 ID 를 직접 사용해서 관계를 억지로 맺음

      // 값 저장 시 
      객체A.setFK(객체B.getID())
      insert(객체A)
      
      // 외래키를 기준으로 호출 시
      "select * from 객체A where 객체A.FK = 객체B.ID"
  • 데이터베이스와 독립적
    • 각 DB 마다 같은 기능이지만 사용하는 방법이 다른 경우가 많다. JPA 를 사용하지 않는 경우 처음 개발할 때 사용한 DB 에 맞춰서 기능을 구현하면 다른 DB를 사용 할 때 다시 수정해야 하는 경우가 발생한다.
    • 예를 들어 페이징 처리
  • 성능
    • JPA 는 성능 최적화 기능을 제공한다.
    • find() 로 조회하는 객체는 처음 조회시에만 DB를 조회하고, 그 이후에 수정사항이 없으면 이미 조회된 객체를 가져온다.

JPA(JAVA Persistence API)

  • JAVA 진영의 ORM 기술에 대한 API 표준 명세, 쉽게 말해 인터페이스를 모아둔 것
    • ORM (Object-Relational Mapping) 은 객체와 관계형 데이터베이스를 매핑한다는 뜻
    • 객체와 테이블을 매핑해서 패러다임의 불일치를 개발자 대신 해결
      • 값을 저장하는 경우, 객체를 자바 컬렉션에 저장하듯이 ORM 프레임워크에 저장한다.
        1. Entity 를 분석
        2. INSERT SQL 을 생성
        3. JDBC API 사용
        4. 패러다임 불일치 해결

엔티티 매니저

  • 엔티티 매니저 팩토리 - 엔티티 매니저를 생성하는 클래스, 여러 스레드가 동시에 접근해도 안전하므로 서로 다른 스레드간에 공유 허용
    • 현재 MustP 프로젝트에서는 기본 생성되는 엔티티매니저 팩토리 사용
  • 엔티티 매니저는 여러 스레드가 동시에 접근 시, 동시성 문제가 발생하므로 스레드 간 공유하면 안됨
  • DB 커넥션을 사용하는 주체로, DB 와 연결되는 객체
  • 객체를 영속 컨텍스트에 저장하는 역할

영속성 컨텍스트

  • 식별자 구분
    • 영속성 컨텍스트는 엔티티를 식별자 값(@Id 로 매핑한 값) 으로 구분하여, 영속 상태는 식별자 값이 반드시 있어야 함
  • 데이터베이스 저장
    • 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영 (플러시)
  • 장점
    • 1차 캐시
      • 영속 컨텍스트 내부에 캐시 데이터가 있어, 조회하려는 엔티티가 1차 캐시 내부에 존재하면 DB를 조회하지 않고, 캐시 데이터로 반환
    • 동일성 보장
      • 1차 캐시 내부에 데이터가 존재하는 경우, 아래 코드가 성립한다

      • 동일한 메모리 주소에 있는 객체를 반환

        객체 A = find("1");
        객체 B = find("1");
        
        if(A == B) 
        	System.out.println("TRUE"); 
    • 트랜잭션을 지원하는 쓰기 지연
    • 변경 감지
      • 영속 상태의 엔티티의 내부 값이 변경되는 경우, 데이터베이스에 자동으로 반영 하는 기능
      • 단, 영속 상태의 엔티티에만 적용됨
    • 지연 로딩
  • 생명주기
    • 비영속 (transient)
      • 영속성 컨텍스트와 전혀 관계가 없는 상태

      • 객체를 막 생성한 상태로, 순수한 자바 객체인 상태

        객체 A = new 객체();
        A.setId(1); 
        A.setName("홍길동");
    • 영속 (managed)
      • 영속성 컨텍스트에 저장된 상태

      • 객체가 영속성 컨텍스트에 관리되는 상태

        EntityManager em = entityManagerFactory.createEntityManager();
        EntityTransaction transaction = em.getTransaction();
        
        // 아래 코드가 현재 영속인 상태 
        transaction.begin(); 
        em.persist(entity);
        transaction.commit(); 
    • 준영속 (detached)
      • 영속성 컨텍스트에 저장되었다가 분리된 상태

      • 영속 상태의 엔티티를 영속성 컨텍스트가 관리하지 않는 상태

        em.detach()
        em.close()
    • 삭제 (removed)
      • 엔티티가 영속성 컨텍스트와 데이터베이스에서 삭제된 상태

        em.remove(entity)

플러시

  • 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영
    • 직접 호출
      • em.flush()
    • 트랜잭션 커밋 시 플러시 자동 호출
    • JPQL 쿼리 실행 시 플러시 자동 호출
      • find() 를 호출할 때는 호출되지 않음
      • FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시 ( 기본값 )
      • FlushModeType.COMMIT : 커밋할 때만 플러시

spring.jpa.hibernate.ddl-auto ( DDL 자동 생성 )

  • none : 실제 유효하지 않는 값으로, 자동 생성 기능을 사용하지 않을 때 많이 사용
  • create : 기존 테이블 삭제 후 테이블 생성, DROP + CREATE
  • create-drop : 기존 테이블 삭제 후 테이블 생성, 종료 시점에 테이블 삭제 DROP + CREATE + DROP
  • update : 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 변경 사항만 수정
  • validate : 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 변경 사항이 있으면 애플리케이션을 실행하지 않음, DDL 을 수정하지 않는다.

update 옵션에서 컬럼 삭제는 엄청난 문제를 발생시킬 수 있기 때문에 컬럼 추가만 반영된다. 개발 초기에는 create 또는 update 옵션을 이용해서 익숙해지는 데 집중하고 추후에 validate 옵션을 설정해주는 것이 좋다.

스테이징, 운영환경에서는 절대로 create, create-drop, update를 사용하면 안된다. 스테이징과 운영 서버에서는 테이블 생성 및 컬럼 추가, 삭제, 변경은 데이터베이스에서 직접하며, none을 사용하거나 validate를 이용해 정상적인 매핑 관계만 확인해야 한다.

0개의 댓글