본문 바로가기
Develop/JPA

[JPA/기본편] JPA

by J-rain 2024. 3. 19.

 

 

JPA - Java Persistence API (자바 진영의 ORM 기술 표준)

ORM

  • Object-relational mapping (객체 관계 매핑)
  • 객체는 객체대로 설계
  • 관계형 데이터베이스는 관계형 데이터베이스대로 설계
  • ORM 프레임워크가 중간에서 매핑
  • 대중적인 언어에는 대부분 ORM 기술이 존재
  • 객체와 관계형 데이터베이스를 매핑한다는 뜻
  • ORM 프레임워크 객체와 테이블을 매핑해서 패러다임의 불일치 문제를 개발자 대신 해결
public class JpaMain {

    public static void main(String[] args) {
        //[엔티티 매니저 팩토리] - 생성
        final EntityManagerFactory emf =
                Persistence.createEntityManagerFactory("hello");
        //[엔티티 매니저] - 생성
        final EntityManager em = emf.createEntityManager();
        //[트랜잭션] - 획득
        final EntityTransaction tx = em.getTransaction();

        try {
            tx.begin();     //[트랜잭션] - 시작
            logic(em);      //비즈니스 로직 실행
            tx.commit();    //[트랜잭션] - 커밋
        } catch (Exception e) {
            tx.rollback();  //[트랜잭션] - 롤백
        } finally {
            em.close();     //[엔티티 매니저] - 종료
        }
        emf.close();        //[엔티티 매니저 팩토리] - 종료
    }
    
    //비즈니스 로직 
    public static void logic(EntityManager em) {}
}

코드는 3부분으로 나눠진다.

  • 앤티티 매니저 설정
  • 트랜잭션 관리
  • 비즈니스 로직

엔티티 매니저 설정부터 살펴보자.

엔티티 매니저란

JPA의 기능 대부분을 제공한다.

엔티티 매니저를 사용해서 엔티티를 데이터베이스에 등록/수정/삭제/조회할 수 있다.

엔티티 매니저 생성 과정은 아래와 같다.

  1. 엔티티 매니저 팩토리 생성
    1.  EntityManagerFactory emf = Persistence.createEntityManagerFactory("...");  
    2. META-INF/persistence.xml에서 persistence-unit을 찾아서 엔티티 매니저 팩토리를 생성한다.
    3. 엔티티 매니저 팩토리는 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용해야 한다.
  2. 엔티티 매니저 생성
    1.  EntityManager em = emf.createEntityManager(); 
    2. 엔티티 매니저 팩토리에서 엔티티 매니저를 생성한다.
    3. 엔티티 매니저는 데이터베이스 커넥션과 밀접한 관계가 있으므로 스레드간에 공유하거나 재사용하면 안된다.
  3. 종료
    1.  em.close()   emf.close() 
    2. 사용이 끝난 엔티티 매니저와 애플리케이션을 종료할 때 엔티티 매니저 팩토리는 반드시 종료해준다.
    3. 그래야 데이터베이스 커넥션이 반환된다. (자세한 내용은 이후에 알아본다.)

 

트랜잭션 관리

JPA를 사용하면 트랜잭션 안에서 데이터를 변경해야 한다.

트랜잭션 없이 데이터를 변경하면 예외가 발생한다.

//[트랜잭션] - 획득
final EntityTransaction tx = em.getTransaction();

try {
    tx.begin();     //[트랜잭션] - 시작
    logic(em);      //비즈니스 로직 실행
    tx.commit();    //[트랜잭션] - 커밋
} catch (Exception e) {
    tx.rollback();  //[트랜잭션] - 롤백
} finally {
    em.close();     //[엔티티 매니저] - 종료
}

기본적으로 비즈니스 로직이 정상 동작하면 트랜잭션을 커밋하고 예외가 발생하면 트랜잭션을 롤백하는 코드를 작성하도록 한다.

 

비즈니스 로직

한 건 조회

 Member member = em.find(Member.class, id); 

등록

 em.persist(member); 

삭제

 em.remove(member); 

수정

Member member = em.find(Member.class, id);
member.setName("member01");

수정은 특이하게  em.update()  또는  em.persist()  같은 메소드 없이 반영된다.

JPA는 어떤 엔티티가 변경되었는지 추적하는 기능을 갖고있다. (영속성 관리에서 자세히 알아보자.)

하나 이상 조회

TypedQuery<Member> query = 
    em.createQuery("select m from Member m", Member.class);
List<Member> members = query.getResultList();

 em.createQuery("select m from Member m", Member.class);  중에서

"select m from Member m"을 보면 SQL과 굉장히 유사하다.

이건 JPA에서 제공하는 JPQL이라고 한다.

 

JPQL과 SQL

JPQL은 SQL과 문법이 거의 유사해서 SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 등을 사용할 수 있다.

JQPL과 SQL의 차이는 아래와 같다.

  • JPQL은 엔티티 객체를 대상으로 쿼리한다. 쉽게 말해 클래스와 필드를 대상으로 쿼리한다.
  • SQL은 데이터베이스 테이블을 대상으로 쿼리한다.

사용 방법

사용방법은 아래와 같다.

  1. em.createQuery(JPQL, 반환 타입) 메소드를 실행한다. TypedQuery<Member> query = em.createQuery("select m from Member m", Member.class); 
  2. 쿼리 객체를 생성한 후 쿼리 객체의 getResultList() 메소드를 호출하면 된다.  List<Member> members = query.getResultList(); 

JPA는 JPQL을 분석해서 적절한 SQL을 만들어 데이터베이스에서 데이터를 조회한다.

(자세한 내용은 객체 지향 쿼리 언어 부분에서 알아보자.)

 

엔티티 매니저 팩토리와 엔티티 매니저

JPA를 사용할 때 반드시 알아야하는 개념인 엔티티 매니저 팩토리와 엔티티 매니저에 대해서 알아보자.

엔티티 매니저 팩토리는 클라이언트의 요청이 왔을 때 엔티티 매니저를 생성하는 역할을 한다.

그리고 생성된 엔티티 매니저는 엔티티를 저장,수정,삭제,조회하는 등 엔티티와 관련된 일을 처리한다.

그림으로 표현하면 아래와 같다.

 

엔티티 매니저 팩토리

역할

엔티티 매니저를 생성한다.

코드

엔티티 매니저 팩토리 객체 생성 코드이다.

EntityManagerFactory emf =
    Persistence.createEntityManagerFactory("jpabook");

이때 META-INF/persistence.xml 에 있는 정보를 바탕으로 EntityManagerFactory 를 생성한다.

 

엔티티 매니저

역할

엔티티 관리자로서 엔티티와 관련된 모든 일을 담당한다.

코드

엔티티 매니저 객체 생성 코드이다.

EntityManager em = emf.createEntityManager();

주의사항

엔티티 매니저는 여로 스레드가 동시에 접근하면 동시성 문제가 발생하므로 스레드 간에 공유하면 안된다.

반면에, 엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전하다.

참고

엔티티 매니저가 DB 커넥션을 얻는 시점 : 엔티티 매니저는 DB 연결이 꼭 필요한 시점에 커넥션을 얻는다. (객체 생성 시점이 아니다.)

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

[JPA/기본편] 연관관계  (1) 2024.03.20
[JPA/기본편] 엔티티 매핑  (0) 2024.03.20
[JPA/기본편] 준영속 상태  (0) 2024.03.20
[JPA/기본편] 플러시  (0) 2024.03.20
[JPA/기본편] 영속성 컨텍스트  (0) 2024.03.20

댓글