[JPA] 3. JPA 시작

Park Yeongseo·2023년 10월 12일
0
post-thumbnail

1. 객체 매핑

CREATE TABLE MEMBER {
	ID VARCHAR (255) NOT NULL,
	NAME VARCHAR(255),
	AGE INTEGER,
	PRIMARY KEY(ID)
}
@Entity
@Table(name = "MEMBER")
public class Member {
	@Id
	@Column(name = "ID")
	private String id;

	@Column(name = "NAME")
	private String username;

	private Integer age;
}
  • @Entity 해당 클래스를 테이블과 매핑한다고 JPA에 알림
  • @Table 엔티티 클래스에 매핑할 테이블 정보. 어노테이션을 생략하면 엔티티 명을 테이블 명으로 매핑
  • @Id 테이블의 PK에 해당하는 필드
  • @Column 필드를 컬럼에 매핑
    • 필드에 매핑 어노테이션을 생략하면 필드명을 사용해서 컬럼명으로 매핑함.
    • 대소문자 구분하지 않음. 대소문자를 구분하는 DB를 사용하는 경우에는 명시적으로 매핑해야 함.

2. 데이터베이스 방언

JPA는 특정 DB에 종속적이지 않지만 각 DB가 제공하는 SQL 문법과 함수에는 조금씩 차이가 있을 수 있다. 이렇게 SQL 표준을 지키지 않거나 특정 DB만의 고유한 기능을 JPA에서는 방언(dialect)이라 한다. 하이버네이트를 포함한 대부분의 JPA 구현체들은 이런 방언을 처리하기 위해 다양한 DB 방언 클래스를 제공한다. 개발자는 JPA가 제공하는 표준 문법에 맞춰 JPA를 사용하면 되고, 특정 DB에 의존적인 SQL은 DB 방언이 처리해준다. 다만 DB 방언을 설정하는 방법은 JPA에 표준화되어 있지 않고 구현체에서 제공한다.

3. 애플리케이션 개발

엔티티 매니저 설정

(1) 엔티티 매니저 팩토리 생성

JPA를 시작하려면 우선 엔티티 매니저 팩토리를 생성해야 한다. 이때는 Persistence클래스 를 사용하는데, 이 클래스는 엔티티 매니저 팩토리를 생성해 JPA를 사용할 수 있게 준비한다.

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

엔티티 매니저 팩토리는 설정 정보를 읽어 JPA 동작을 위한 기반 객체도 만들고 DB 커넥션 풀도 생성하는 등, 생성 비용이 매우 크므로 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용해야 한다.

(2) 엔티티 매니저 생성

엔티티의 DB 등록/수정/삭제/조회 등 JPA의 대부분의 기능은 엔티티 매니저가 제공한다.엔티티 매니저는 내부에 데이터소스(DB 커넥션)를 유지하면서 DB와 통신한다.

다만 엔티티 매니저는 DB 커넥션과 밀접한 관계가 있으므로 스레드 간에 공유하거나 재사용해서는 안된다.

(3) 종료

사용이 끝난 엔티티 매니저는 반드시 종료해야하고, 애플리케이션을 종료할 때에는 팩토리도 종료해주어야 한다.

트랜잭션 관리

JPA를 사용하면 항상 트랜잭션 내에서 데이터를 변경해야 하며, 트랜잭션 없이 데이터를 변경하면 예외가 발생한다. 트랜잭션을 시작하기 위해서는 엔티티 매니저로부터 트랜잭션 API를 받아와야 한다.

EntityTransaction tx = em.getTransaction();
try {
	tx.begin();
	logic(em);
	tx.commit();
} 
catch (Exception e) {
	tx.rollback();
}

트랜잭션 API로 비즈니스 로직이 정상 동작하면 커밋, 예외가 발생하면 롤백한다.

비즈니스 로직

비즈니스 로직에서의 등록, 수정, 삭제, 조회 등은 엔티티 매니저를 통해 이루어진다.

(1) 등록

엔티티의 저장은 엔티티 매니저의 persist()메소드에 저장할 엔티티를 넘겨서 이루어진다.

Member member = new Member(...); //이러저런 Member 객체 member를 만들고
em.persist(member); //member를 저장

(2) 수정

엔티티를 수정한 후에 수정 내용을 반영하기 위해서는 em.update()와 같은 메서드를 호출할 필요가 없이 단순히 엔티티의 값만 변경하며 된다. JPA는 어떤 엔티티가 변경되었는지 추적하는 기능을 갖추고 있기 때문에, 엔티티의 값만 변경하면 UPDATE SQL을 생성해서 데이터베이스에 값을 변경한다. 사실 em.update()같은 메서드도 없다.

(3) 삭제

em.remove(member)와 같이 삭제할 엔티티를 넘겨서 삭제한다.

(4) 한 건 조회

find(Member.class, id)처럼, 메소드에 조회할 엔티티의 클래스와 PK에 매핑한 식별자 값으로 조회할 수 있다. 이때 조회한 값으로 Member클래스의 엔티티를 생성해 반환한다.

4. JPQL(Java Persistence Query Language)

JPA를 사용하면 개발자는 엔티티 객체를 중심으로 개발하고 데이터베이스에 대한 처리는 JPA에 맡겨야 한다. 문제는 검색 쿼리를 날려야 하는 경우, DB의 모든 객체를 불러와 엔티티 객체로 변환하고 검색해야 하는데, 이는 불가능하다.

필요한 데이터만 DB에서 불러오기 위해서는 검색 조건이 포함된 SQL을 사용해야 하는데, JPA는 JPQL이라는 쿼리 언어로 이러한 문제를 해결한다. 이는 SQL을 추상화한 객체지향 쿼리 언어로, 문법은 SQL과 거의 유사하지만, DB 테이블을 대상으로 쿼리하는 SQL과 달리 엔티티 객체를 대상으로 쿼리를 한다는 점에서 차이가 있다.

JPQL을 사용하기 위해서는 em.createQuery(JPQL, 반환 타입)메소드를 실행해 쿼리 객체를 생성하고, 쿼리 객체의 getResultList()메소드를 호출하면 된다. JPA는 JPQL을 분석해 적절한 SQL을 만들어 DB에서 조회한다.

profile
블로그 이전 준비 중

0개의 댓글