자바 ORM 표준 JPA 프로그래밍 - 2장, JPA 시작
자바 ORM 표준 JPA 프로그래밍에서 읽은 내용을 정리하는 글입니다😄
2.1 ~ 2.2 IntelliJ 프로젝트 설정하기, H2 데이터베이스 설치
책에서는 이클립스로 하지만 이전 강의에서 이클립스보다 IntelliJ가 편하다고 언급하셔서
이미 설치돼 있는 IntelliJ로 진행하기로 했다. 김영한님의 글 참고.
2.3 라이브러리와 프로젝트 구조
요즘은 필요한 라이브러리를 일일이 다운로드받아 적용시키지 않고 maven이나 gradle을 사용한다.
책에서는 maven으로 진행하는데, pom.xml
에 사용할 라이브러리를 적어주면 자동으로 내려받아 관리한다.
<dependency>
에 사용할 라이브러리의 groupId, artifactId, version을 적어주면 된다.
JPA 구현체인 하이버네이트를 사용하기 위한 핵심 라이브러리는 다음과 같다.
- hibernate-core : 하이버네이트 라이브러리
- hibernate-entityManager : 하이버네이트가 JPA 구현체로 동작하도록 JPA 표준을 구현한 라이브러리
- hibernate-jpa-2.1-api : JPA 2.1 표준 API를 모아둔 라이브러리
또한 H2 데이터베이스에 접속하기 위해 h2 라이브러리도 지정해야 한다.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2db.version}</version>
</dependency>
2.4 객체 매핑 시작
사용할 회원 테이블을 만들기 위해 H2 데이터베이스에서 다음의 코드를 입력하자.
CREATE TABLE MEMBER (
ID VARCHAR(255) NOT NULL,
NAME VARCHAR(255),
AGE INTEGER,
PRIMARY KEY (ID)
)
그리고 사용할 회원 클래스를 애플리케이션에서 만들어주자.
회원 클래스와 회원 테이블의 실제 매핑을 해보자.
매핑 정보 | 회원 객체 | 회원 테이블 |
---|---|---|
클래스와 테이블 | Member | MEMBER |
기본 키 | id | ID |
필드와 컬럼 | username | NAME |
필드와 컬럼 | age | AGE |
이제 위의 회원 클래스에서 JPA가 제공하는 매핑 어노테이션을 추가해보자.
@Entity
: 클래스를 테이블과 매핑. 적용된 클래스를 엔티티 클래스라 부름.@Table
: 엔티티 클래스에 매핑할 테이블의 정보를 알려줌.@Id
: 테이블의 기본 키(primary key)에 매핑. 해당 필드는 식별자 필드라 부름.@Column
: 필드를 컬럼에 매핑. name 속성을 사용해 테이블의 해당 컬럼에 매핑.- 매핑이 없으면 : 필드명을 컬럼명으로 매핑. (대소문자 구분X)
2.5 persistence.xml 설정
JPA에서 필요한 설정 정보를 관리하기 위해 persistence.xml을 사용한다.
META-INF/persistence.xml
에 있으면 별도 설정 없이 JPA가 인식할 수 있다고 한다.
XML 네임스페이스와 사용할 JPA 버전을 입력한다.
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
JPA는 영속성 유닛(persistence-unit) 등록부터 해야하는데 jpabook이라는 이름으로 설정한다.
<persistence-unit name="jpabook">
속성(properties)중에는 어떤 내용이 있는지 알아보자.
javax.persistence.jdbc.driver
: JDBC 드라이버javax.persistence.jdbc.user
: 데이터베이스 접속 아이디javax.persistence.jdbc.password
: 데데이터베이스 접속 비밀번호javax.persistence.jdbc.url
: 데이터베이스 접속 URLhibernate.dialect
: 데이터베이스 방언 설정
데이터베이스 방언
JPA는 다른 데이터베이스로 쉽게 교체할 수 있지만 데이터베이스마다 제공하는 SQL 문법과 함수가
조금씩 다르다는 문제점이 존재한다. 이 때 SQL 표준을 지키지 않거나 고유한 기능을 방언이라 한다.
JPA 구현체들은 이런 문제를 해결하기 위해 데이터베이스 방언 클래스를 제공한다.
2.6 애플리케이션 개발
코드는 3단계로 나뉘게 된다.
- 엔티티 매니저 설정
- 트랜잭션 관리
- 비즈니스 로직
엔티티 매니저 팩토리 생성
JPA를 시작하려면 엔티티 매니저 팩토리를 생성해야 한다. 이 때 persistence.xml를 사용한다.
위에서 영속성 유닛으로 jpabook
을 설정했었는데 이 값을 인자로 활용한다.
엔티티 매니저 팩토리를 생성하는 비용은 아주 크므로 한 번만 생성하고 공유해서 사용해야 한다.
//엔티티 매니저 팩토리 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
엔티티 매니저 생성
JPA 기능 대부분은 엔티티 매니저가 제공한다.
엔티티 매니저는 내부 데이터소스를 유지하면서 데이터베이스와 통신하기 때문에
개발자는 엔티티 매니저를 가상의 데이터베이스로 생각할 수 있다.
(데이터베이스 커넥션과 관계가 있어 스레드 간 공유 또는 재사용하면 안된다)
EntityManager em = emf.createEntityManager(); //엔티티 매니저 생성
트랜잭션 관리
JPA 사용 시 반드시 트랜잭션 안에서 데이터를 변경해야 한다. 그렇지 않으면 예외가 발생한다.
위 코드에서 try문 안에 있는 주석을 참고하자.
비즈니스 로직
회원 엔티티를 하나 생성 후 엔티티 매니저를 통해 등록/수정/삭제/조회하는 과정이다.
출력 결과는 다음과 같다.
findMember=지한, age=20
members.size=1
자세히 보면 등록 후 수정을 했는데 uplast_modified_at를 별도로 하지 않았음에도 출력 결과에 반영이 됐다.
어떻게 이럴 수 있을까? JPA는 어떤 엔티티가 변경됐는지 추적하는 기능을 갖고 있어서 가능하다.
따라서 위처럼 age를 변경했을 때 UPDATE SQL을 생성해서 데이터베이스에서 값을 변경한다고 한다.
실제로 엔티티 매니저에 uplast_modified_at 관련 메소드는 없다.
JPQL(Java Persistence Query Language)
JPA를 사용하는 애플리케이션 개발자는 엔티티 객체를 중심으로 개발하고 데이터베이스 처리는 JPA에
맡겨야 한다. 근데 테이블이 아닌 객체로 검색하려면 모든 데이터를 객체로 변환하는 작업을 거쳐야
한다. 이런 과정은 매우 비효율적이므로 JPA는 SQL을 추상화한 JPQL을 사용한다.
가장 큰 차이점은 다음과 같다.
- JPQL은 엔티티 객체를 대상으로 한다. 즉, 클래스와 필드를 대상으로 한다.
- SQL은 데이터베이스 테이블을 대상으로 한다.
목록 조회 코드에서 select m from Member m
이 바로 JPQL이 적용된 예시다.
댓글남기기