본문 바로가기
개인 공부/JPA (자바 ORM 표준 JPA 프로그래밍)

자바 ORM 표준 JPA 프로그래밍 : JPA 시작 (2장)

by 희조당 2022. 9. 15.
728x90

 


📌 객체 매핑 시작

JPA를 사용하려면 가장 먼저 클래스와 테이블과의 매핑이 필요하다.

매핑을 위해서 JPA에서 제공하는 어노테이션(javax.persistence.*)을 추가해야 한다. 

🌀Entity

클래스를 테이블과 매핑한다고 JPA에게 알려주는 어노테이션이다.

이 어노테이션이 붙은 클래스를 엔티티 클래스라고 부른다.

🌀Table

엔티티 클래스에 매핑할 테이블 정보를 알려주는 어노테이션이다.

name 속성으로 어떤 테이블과 매핑할지 설정할 수 있다. 만약 생략한다면 엔티티 이름을 사용한다.

🌀Id

엔티티 클래스의 필드를 기본 키(PK)에 매핑하는 어노테이션이다.

이 어노테이션이 붙은 필드를 식별자 필드라고 한다.

🌀Column

필드를 칼럼에 매핑하는 어노테이션이다.

매핑 어노테이션을 생략하면 필드명을 사용해서 column명으로 매핑한다.

단, 데이터베이스에서 대소문자를 구분한다면 꼭 명시적으로 매핑해야 한다.


📌 persistence.xml 설정

이 책에서 사용하는 빌드 툴인 maven은 persistence.xml을 통해서 설정 정보를 관리한다.

설정을 위해 사용한 속성들은 다음과 같다.

🧷 JPA 표준 속성

  • javax.persistence.jdbc.driver : JDBC 드라이버
  • javax.persistence.jdbc.user : 데이터베이스 접속 아이디
  • javax.persistence.jdbc.password ; 데이터베이스 접속 비밀번호
  • javax.persistence.jdbc.url : 데이터베이스 접속 url

🧷 하이버네이트 속성

  • hibernate.dialect : 데이터베이스 방언 설정

✔️ 데이터베이스 방언, Dialect

데이터베이스마다 문법이 조금씩 다르다는 문제가 있다. (ex. 데이터 타입, 함수명, 페이징 처리)

이처럼 SQL 표준을 지키지 않거나 특정 데이터베이스만의 고유한 기능을 방언이라고 한다.

방언을 제공함으로 데이터베이스에 종속적이지 않아 다른 데이터베이스로 쉽게 교체할 수 있는 것이다.

따라서 개발자는 JPA 표준만 지키면 되고, 특정 데이터베이스에 의존적인 SQL은 방언이 처리해준다.

하이버네이트에서 제공하는 대표적인 데이터베이스 방언은 다음과 같다.

  • H2 : org.hibernate.dialect.H2Dialect
  • 오라클 10g : org.hibernate.dialect.Oracle10gDialect
  • MySQL : org.hibernate.dialect.MySQL5InnoDBDialect

📌 애플리케이션 개발

public static void main(String[] args) {
   //엔티티 매니저 팩토리 생성
   EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
   EntityManager em = emf.createEntityManager(); //엔티티 매니저 생성

   EntityTransaction tx = em.getTransaction(); //트랜잭션 기능 획득

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

   emf.close(); //엔티티 매니저 팩토리 종료
}

코드는 크게 엔티티 매니저 설정, 트랜잭션 관리, 비지니스 로직 3부분으로 나뉜다.

 

🧷 엔티티 매니저 설정

엔티티 매니저 생성 과정

1️⃣ 엔티티 매니저 팩토리 생성

  • JPA를 시작하기 위해 우선 팩토리를 생성해야 한다.
  • Persistence 클래스를 사용해 persistence.xml의 설정 정보를 읽어와 JPA를 동작시키기 위한 기반 객체를 만들고 JPA 구현체에 따르는 데이터베이스 커넥션 풀도 생성한다. 
  • 이렇게 팩토리를 생성하는 비용이 너무 크므로 딱 한 번만 생성하고 공유해서 사용해야 한다.

2️⃣ 엔티티 매니저 생성

  • 엔티티 매니저 팩토리에서 JPA의 기능 대부분을 제공하는 엔티티 매니저를 생성한다.
  • 엔티티 매니저는 내부에 데이터 소스(Connection)를 유지하며 데이터베이스와 통신한다.
  • 데이터베이스 커넥션과 밀접한 관련이 있어 스레드 간에 공유 또는 재사용 금지다.

3️⃣ 종료

  • 사용이 끝난 매니저는 반드시 종료해야 한다.
  • 애플리케이션이 종료될 때 팩토리를 종료해야 한다. (딱 한번 생성하기 때문에)

🧷 트랜잭션 관리

JPA는 항상 트랜잭션 안에서 데이터를 변경해야 한다. 만약 트랜잭션이 없다면 예외가 발생한다.

엔티티 매니저에서 트랜잭션 API를 받아와 비지니스 로직을 시도해서 정상 작동하면 커밋, 아니라면 롤백한다.

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

🧷 비지니스 로직

엔티티 매니저를 통해서 데이터베이스에 등록, 수정, 삭제, 조회한다.

각 코드를 분석해보자.

 

1️⃣ 등록

String id = "id1";
Member member = new Member();
member.setId(id);
member.setUsername("지한");
member.setAge(2);

//등록
em.persist(member);
  • 등록은 엔티티 매니저의 persist() 메서드를 사용한다.
  • JPA는 회원 엔티티의 매핑 정보(어노테이션)를 분석해서 데이터베이스에 전달한다.

2️⃣ 수정

//수정
member.setAge(20);
  • 수정은 보통 update()를 생각하는데 그런 메서드는 없다.
  • JPA는 엔티티의 변경을 추적하는 기능을 가지고 있어 엔티티 값을 변경하면 UPDATE SQL을 생성한다.

3️⃣ 삭제

//삭제
em.remove(member);
  • remove() 메서드를 사용해서 삭제한다. JPA는 DELETE SQL을 생성한다.

4️⃣ 한 건 조회

//한 건 조회
Member findMember = em.find(Member.class, id);
  • find() 메서드는 엔티티 타입과 기본 키와 매핑한 식별자 값으로 조회하는 가장 단순한 find 메서드이다.
  • JPA는 SELECT SQL을 생성하고 결과 값으로 엔티티를 생성해 리턴한다.

🧷 JPQL

JPA는 엔티티 객체를 중심으로 개발하므로 검색할 때도 테이블이 아니라 엔티티를 대상으로 검색한다.

근데 문제는 여러 목록을 조회하려면 모든 데이터를 불러와 엔티티를 변경한 후 검색해야 하는데 사실상 불가능하다.

이런 문제를 해결하기 위해서 JPA는 JPQL이라는 쿼리 언어를 제공한다.

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

JPQL은 SQL이 추상화된 객체지향 쿼리 언어를 제공하고 기존 SQL 언어와 다음과 같은 차이점을 가진다.

  • JPQL : 엔티티 객체(Class, Filed)를 대상으로 쿼리, 테이블을 전혀 모른다.
  • SQL : 테이블을 대상으로 쿼리

 

댓글