이 글은 김영한 저, 자바 ORM 표준 JPA 프로그래밍 책을 정리한 글입니다. 모든 출처는 해당 책에 있습니다.

메이븐(Maven) : 라이브러리를 관리하고 빌드하는 도구. pom.xml의 <dependencies>에 사용할 라이브러리를 지정한다. groupId + artifactId + version만 적어주면 라이브러리(jar 파일)를 메이븐 공식 저장소에서 내려받아 라이브러리에 추가해준다.


매핑 어노테이션에 따른 매핑 과정
@Entity : 이 클래스를 테이블과 매핑한다고 JPA에게 알려준다. (이 어노테이션이 쓰인 클래스를 엔티티 클래스라 부름)
@Table : 엔티티 클래스에 매핑할 테이블 정보를 알려준다. 이 어노테이션을 생략하면 클래스 이름을 테이블 이름으로 매핑한다. (더 정확히는 엔티티 이름을 사용한다.)
@Id : 엔티티 클래스의 필드를 테이블의 기본 키(Primary key)에 매핑한다. (이 어노테이션이 쓰인 필드를 식별자 필드라 부름)
@Column : 필드를 칼럼에 매핑한다.
매핑 정보가 없는 필드 : 매핑 어노테이션을 생략하면 필드명을 사용해서 칼럼명으로 매핑한다. 


persistence.xml (JPA 어노테이션의 패키지) : 이 설정 파일이 META-INF/persistence.xml 클래스 패스 경로에 있으면 별도의 설정 없이 JPA가 인식할 수 있다.

<?xml version="1.0" encoding="UTF-8"?>
<!-- 설정 파일은 persistence로 시작한다. 이곳에 XML 네임 스페이스와 사용할 버전을 지정한다. -->
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
	<!-- JPA 설정은 영속성 유닛(persistence-unit)이라는 것부터 시작한다. 
		일반적으로 연결할 데이터베이스당 하나의 영속성 유닛을 등록한다. 
		영속성 유닛에는 고유한 이름을 부여해야 하는데 여기서는 jpabook이라는 이름을 사용했다.-->
    <persistence-unit name="jpabook">

        <properties>

            <!-- 필수 속성 -->
            	<!-- JPA 표준 속성(특정 구현체에 종속되지 않음)
            	위에서부터, JDBC 드라이버, 
                데이터베이스 접속 아이디, 
                데이터베이스 접속 비밀번호, 
                데이터베이스 접속 URL, 
                데이터베이스 방언(Dialect)설정 -->
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>
            	<!-- 하이버네이트 속성(하이버네이트 내에서만 사용 가능) -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />

            <!-- 옵션 -->
            	<!-- 위에서부터, 하이버네이트가 실행한 SQL을 출력한다.
            	하이버네이트가 실행한 SQL을 출력할 때 보기 쉽게 정렬한다.
            	쿼리를 출력할 때 주석도 함께 출력한다.
            	JPA 표준에 맞춘 새로운 키 생성 전략을 사용한다. -->
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.use_sql_comments" value="true" />
            <property name="hibernate.id.new_generator_mappings" value="true" />

            <!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
        </properties>
    </persistence-unit>

</persistence>

데이터베이스 방언(Dialect) : SQL 표준을 지키지 않거나 특정 데이터베이스만의 고유한 기능을 JPA에서 지칭하는 용어
예를 들면 MYSQL의 VARCHAR, ORACLE의 VARCHAR2가 있다.


엔티티 매니저 설정

package jpabook.start;

import javax.persistence.*;
import java.util.List;

/**
 * @author holyeye
 */
public class JpaMain {

	/**
	 *	코드는 크게 3부분으로 나뉘어져 있다.
	 *	엔티티 매니저 설정
	 *	트랜잭션 관리
	 *	비즈니스 로직 
	 */
	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(); // 엔티티 매니저 팩토리 종료
	}

	public static void logic(EntityManager em) {

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

		// 등록
		em.persist(member);

		// 수정
		member.setAge(20);

		// 한 건 조회
		Member findMember = em.find(Member.class, id);
		System.out.println("findMember=" + findMember.getUsername() + ", age=" + findMember.getAge());

		// 목록 조회
		List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
		System.out.println("members.size=" + members.size());

		// 삭제
		em.remove(member);

	}
}

엔티티 매니저 생성 과정

엔티티 매니저 팩토리 생성: JPA를 시작하려면 우선 persistence.xml의 설정 정보를 사용해서 엔티티 매니저 팩토리를 생성해야 한다. 이때 Persistence 클래스를 사용한다.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
이렇게 하면 META-INF/persistence.xml에서 이름이 jpabook인 영속성 유닛을 찾아서 엔티티 매니저 팩토리를 생성한다. 
주의할 점은 엔티티 매니저 팩토리는 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용해야 한다.
(persistence.xml의 설정 정보를 읽어서 JPA를 동작시키기 위한 기반 객체를 만들고 JPA구현체에 따라서는 데이터베이스 커넥션 풀도 생성하므로 엔티티 매니저 팩토리를 생성하는 비용은 아주 크기 때문)

엔티티 매니저 생성: EntityManager em = emf.createEntityManager();
엔티티 매니저 팩토리에서 엔티티 매니저를 생성한다. JPA의 기능 대부분은 이 엔티티 매니저가 제공함. 대표적으로 엔티티 매니저를 사용해서 엔티티를 데이터베이스에 등록/수정/삭제/조회(CRUD)할 수 있다. 
엔티티 매니저는 내부에 데이터 소스(데이터 커넥션)를 유지하면서 데이터베이스와 통신한다. 따라서 애플리케이션 개발자는 엔티티 매니저를 가상의 데이터베이스로 생각할 수 있다. (엔티티 매니저는 데이터베이스 커넥션과 밀접한 관계가 있으므로 스레드 간에 공유하거나 재사용하면 안 된다.)

종료: 마지막으로 사용이 끝난 엔티티 매니저는 반드시 종료해야 한다.
em.close();
애플리케이션을 종료할 때 엔티티 매니저 팩토리도 종료해야 한다.
emf.close();


트랜잭션 관리

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

		try {

			tx.begin(); // 트랜잭션 시작
			logic(em); // 비즈니스 로직
			tx.commit();// 트랜잭션 커밋

		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback(); // 트랜잭션 롤백
		}

JPA를 사용할 때 항상 트랜잭션 안에서 데이터를 변경해야 한다.
먼저 엔티티 매니저(em)에서 트랜잭션 API를 받아와야 한다.
트랜잭션을 시작하고, 비즈니스 로직이 정상 동작하면 트랜잭션 커밋하고 예외가 발생하면 롤백한다.


비즈니스 로직

package jpabook.start;

import javax.persistence.*;
import java.util.List;

/**
 * @author holyeye
 */
public class JpaMain {

	/**
	 *	코드는 크게 3부분으로 나뉘어져 있다.
	 *	엔티티 매니저 설정
	 *	트랜잭션 관리
	 *	비즈니스 로직 
	 */
	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(); // 엔티티 매니저 팩토리 종료
	}

	public static void logic(EntityManager em) {

		
//		엔티티를 저장하려면 엔티티 매니저의 persist() 메소드에 저장할 엔티티를 넘겨주면 된다.
		String id = "id1";
		Member member = new Member();
		member.setId(id);
		member.setUsername("지한");
		member.setAge(2);

		// 등록
		em.persist(member);

		// 수정
//		단순히 엔티티의 값만 변경해도 JPA는 어떤 엔티티가 변경되었는지 추적하는 기능을 갖고 있기 때문에 별도의 처리없이 수정 작업을 진행할 수 있다.
		member.setAge(20);

		// 한 건 조회
//		find() 메소드는 조회할 엔티티 타입과 @Id로 데이터베이스 테이블의 기본 키와 매핑한 식별자 값으로 엔티티 하나를 조회하는 가장 단순한 조회 메소드이다.
		Member findMember = em.find(Member.class, id);
		System.out.println("findMember=" + findMember.getUsername() + ", age=" + findMember.getAge());

		// 목록 조회
//		JPQL(Java Persistence Query Language) : JPA가 사용하는 SQL을 추상화한 객체지향 쿼리 언어. 
//		JPQL은 엔티티 객체(클래스와 필드)를 대상으로 쿼리하고 SQL은 데이터베이스 테이블을 대상으로 쿼리한다.
//		또한 JPQL은 대소문자를 명확히 구분하지만 SQL은 관례상 대소문자를 구분하지 않고 사용하는 경우가 많다.
		List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
		System.out.println("members.size=" + members.size());

		// 삭제
//		JPA 내부에서는 DELETE FROM MEMBER WHERE ID = 'id1' 이라는 SQL을 생성해서 실행한다.
		em.remove(member);

	}
}

회원 엔티티를 하나 생성한 다음 엔티티 매니저(em)를 통해 데이터베이스에 등록, 수정, 삭제, 조회한다.

+ Recent posts