[Spring] JPA

zini9188·2023년 2월 24일
0

Spring

목록 보기
23/33

JPA란

Java Persistence API의 약자(Jakarta Persistence 라고도 불림)로, Java 진영에서 사용하는 ORM 기술 표준으로 사용되는 인터페이스의 모음이다. 즉, 실제로 구현된 것이 아닌 구현된 클래스와의 매핑을 위해 사용되는 프레임워크이다. 대표적으로는 Hibernate ORM, EclipseLink, DataNucleus 등이 존재한다.

Hibernate ORM

JPA에서 정의해둔 인터페이스를 구현한 구현체로, JPA에서 지원하는 기능 이외에 자체적으로 사용할 수 있는 API도 지원하고 있다.

JPA는 데이터 액세스 계층의 상단에 위치하며, 실제 작업은 JPA를 거쳐 구현체인 Hibernate ORM을 통해 이뤄진다.

이 때, Hibernate ORM은 내부적으로 JDBC API를 이용해 데이터베이스에 접근한다.

JPA의 장점

  • SQL문이 아닌 Method로 데이터베이스를 조작할 수 있어, 객체 모델을 이용하여 비즈니스 로직을 구성하는 것에만 집중할 수 있다.

  • Query와 같이 필요한 선언문, 할당 등의 부수적인 코드가 줄어들어 가독성이 높아지고 코드가 간결해진다.

  • 객체지향적 접근만 가능하므로 생산성이 증가한다.

  • 매핑하는 정보가 Class로 명시되어, ERD를 봐야하는 의존도가 낮아지며, 유지보수 및 리팩토링에 유리하다.

  • 데이터베이스를 변경할 때 ORM을 사용하기에 쿼리 수정이 필요가 없다.

JPA의 단점

  • 프로젝트의 규모가 크고 복잡하여 설계가 잘못되면, 속도 저하 및 일관성이 무너지는 문제점이 생길 수 있다.

  • 복잡하고 무거운 Query는 속도를 위해 별도의 튜닝이 필요하여 결국 SQL문이 필요할 수 있다.

  • 러닝커브가 존재한다.

JPA의 Persistence

Persistence란 영속성, 지속성이라는 뜻을 가지는데, 무언가가 지속되게 하는 것이 Persistence의 목적이다.

영속성 컨텍스트

ORM은 객체와 데이터베이스 테이블의 매핑을 통해 엔티티 클래스 안에 포함된 정보를 테이블에 저장하는 기술이다.

JPA에서는 테이블과 매핑되는 엔티티 객체 정보를 영속성 컨텍스트라는 곳에 보관하고, 이를 애플리케이션 내에서 오래 지속되도록 해준다.

이렇게 보관된 엔티티 정보를 가지고 데이터베이스 테이블의 데이터를 저장, 수정, 조회, 삭제하는 데 사용한다.

영속성 컨텍스트에는 두 가지 영역이 존재한다.

  1. 1차 캐시
    JPA API 중 엔티티 정보를 영속성 컨텍스트에 저장하는 persist API를 사용하면 1차 캐시에 엔티티 정보가 저장된다.

  2. 쓰기 지연 SQL 저장소

영속성 컨텍스트에 변경이 발생할 경우, 바로 데이터베이스로 쿼리를 보내지 않고 SQL 쿼리를 버퍼에 모아뒀다가, 영속성 컨텍스트가 flush되는 시점에 모아둔 SQL 쿼리를 데이터베이스로 보내는 역할

JPA 설정하기

라이브러리 설정

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

yml 파일 설정

spring:
  h2:
    console:
      enabled: true
      path: /h2     
  datasource:
    url: jdbc:h2:mem:test
  jpa:
    hibernate:
      ddl-auto: create  # (1) 스키마 자동 생성
    show-sql: true      # (2) SQL 쿼리 출력

JPA 사용하기

우선 JPA를 사용하기 위해 Entity 클래스가 필요하다.

@Getter
@Setter
@NoArgsConstructor
@Entity
public class Member{
	@Id
    @GenaratedValue
	private Long memberId;    
    private String email;
    public Member(String email){
    	this.email = email;
    }
}

@Entity, @Id 어노테이션을 추가하여, JPA가 Member 클래스를 엔티티 클래스로 인식하게 한다.

@Configuration
public class JpaBasicConfig {
    private EntityManager em;
    private EntityTransaction tx;
    
    @Bean
    public CommandLineRunner testJpaBasicRunner(EntityManagerFactory emFactory) {
        this.em = emFactory.createEntityManager();
        this.tx = em.getTransaction();
        return args -> {
                example03();
        };
    }

    private void example03() {
        tx.begin();            
        Member member1 = new Member("abc1@gmail.com");
        Member member2 = new Member("abc2@gmail.com");
        em.persist(member1);  // (1)
        em.persist(member2);  // (2)		
        tx.commit(); // (3)
     }
}

@Configuration

스프링에서 Bean 검색 대상인 클래스로 간주하여 @Bean 어노테이션이 추가된 메서드를 검색한 후 해당 메서드에서 리턴하는 객체를 스프링 빈으로 추가해준다.

CommandLineRunner

CommandLineRunner 객체를 람다 표현식으로 정의하면, 애플리케이션 부트스트랩 과정이 완료된 후에 해당 람다 표현식에 정의한 코드를 실행한다.

EntityManager

JPA의 영속성 컨텍스트는 EntityManager 클래스에 의해 관리되며, 이 EntityManager의 객체는 스프링으로부터 DI를 통해 EntityManagerFactory의 객체를 받아 createEntityManager() 메서드로 받아올 수 있다.

EntityTranscation

EntityManager 객체로부터 Transcation 객체를 얻을 수 있고, JPA에서는 Transaction 객체를 기준으로 데이터베이스의 테이블에 데이터를 저장한다.

persist()

해당 메서드를 호출하면 영속성 컨텍스트에 객체의 정보를 저장할 수 있다.

find()

해당 메서드로 영속성 컨텍스트에 저장된 객체를 조회할 수 있다.

find() 메서드는 두 개의 파라미터가 있는데, 첫 번째 파라미터는 조회할 엔티티 클래스의 타입이고, 두 번째 파라미터는 조회할 엔티티 클래스의 식별자 값이다.

commit()

해당 메서드를 통해, 영속성 컨텍스트에 저장되어 있는 객체를 데이터베이스의 테이블에 저장할 수 있다.

flush()를 사용하여 변경 사항을 반영할 수 있지만, commit()을 호출하면 내부적으로 flush()가 호출된다.

remove()

해당 메서드를 통해, 영속성 컨텍스트의 1차 캐시에 있는 엔티티를 제거할 수 있다.

profile
백엔드를 지망하는 개발자

0개의 댓글