2. JPA 시작
1. 객체 매핑 시작
- 클래스와 테이블을 매핑하기 위해 어노테이션을 사용함
 import javax.persistence.* @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에게 알려줌
 - @Entity 어노테이션이 사용된 클래스를 
엔티티 클래스라고 함 
 - @Table
- 엔티티 클래스에 매핑할 테이블 정보를 알려줌
 - 위에서는 
name속성을 사용해서 Member 클래스를 MEMBER 테이블에 매핑함 - 이 어노테이션을 생략하면 클래스 이름을테이블 이름으로 매핑함(정확히는 엔티티 이름을 사용)
 
 - @Id
- 엔티티 클래스의 필드를 테이블의 기본 키
Primary key에 매핑한다 - @Id 어노테이션이 사용된 필드를 
식별자 필드라고 함 
 - 엔티티 클래스의 필드를 테이블의 기본 키
 - @Column
- 필드를 컬럼에 매핑함
 - 여기서는 
name속성을 사용해서 Member 엔티티의 username 필드를 MEMBER 테이블의 NAME 컬럼에 매핑했음 
 - 매핑 정보가 없는 필드
- 위에서 age 필드와 같이 어노테이션을 생략한 필드는 필드명을 사용해서 컬럼명으로 매핑함
 - 대소문자를 구분하는 데이터베이스를 사용하면 명시적으로 매핑해야 함
@Column(name="AGE") 
 
2. persistence.xml 설정
- JPA는 persistence.xml을 사용해서 필요한 설정 정보를 관리함
 META-INF/persistence.xml클래스 패스 경로에 있으면 별도의 설정 없이 JPA가 인식 가능함
  <!-- 전체 코드 -->
  <?xml version="1.0" encoding="UTF-8"?>
  <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
    <persistence-unit name="jpabook">
      <properties>
        <!-- 필수 속성 -->
        <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.H2Dialect"/>
        <!-- 옵션 -->
        <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"/>
      </properties>
    </persistence-unit>
  </persistence>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">- XML 네임스페이스와 사용할 버전을 지정, 위와 같이 2.1로 지정
 
<persistence-unit name="jpabook">- JPA 설정은 영속성 유닛persistence-unit 부터 시작
 - 일반적으로 연결할 데이터베이스당 하나의 영속성 유닛을 등록
 - “jpabook”과 같은 고유한 이름을 부여해야 함
 
<properties> <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>- JPA 표준 속성
<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"/>
 - 하이버네이트 속성
hibernate,dialect: 데이터베이스 방언dialect 설정
 
- JPA 표준 속성
 
3. 데이터베이스 방언(Dialect)
- 데이터베이스 방언이란?
- SQL 표준을 지키지 않거나 특정 데이터베이스만의 고유한 기능 또는 형식
- 데이터타입 : MySQL에서는 
VARCHAR, 오라클은VARCHAR2 - 다른 함수명 : 문자열을 자르는 함수를 SQL 표준에서는 
SUBSTRING(), 오라클은SUBSTR()사용 - 페이징처리 : MySQL은 
LIMIT사용, 오라클은ROWNUM사용 
 - 데이터타입 : MySQL에서는 
 
 - SQL 표준을 지키지 않거나 특정 데이터베이스만의 고유한 기능 또는 형식
 - 데이터베이스의 종속성이 커져서 결국 데이터베이스 교체가 어려워짐
 - 하이버네이트를 포함한 대부분의 JPA 구현체들은 이런 문제를 해결하기 위해 
데이터베이스 방언 클래스를 제공함 
- H2 : org.hibernate.dialect.H2Dialect
 - 오라클 10g : org.hibernate.dialect.Oracle10gDialect
 - MySQL : org.hibernate.dialect.MySQL5InnoDBDialect
 
4. 애플리케이션 개발
  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) {
        tx.rollback();          // [트랜잭션] - 롤백
    } finally {
        em.close();            // [엔티티 매니저] - 종료
    }
    emf.close();               // [엔티티 매니저 팩토리] - 종료
  }
- 크게 세 부분으로 나뉘어짐
- 엔티티 매니저 설정
 - 트랜잭션 관리
 - 비즈니스 로직
 
 
4.1 엔티티 매니저 설정
- 엔티티 매니저 팩토리 설정

- 엔티티 매니저 팩토리 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");persistence.xml에서 이름이jpabook인 영속성 유닛persistence-unit을 찾아서 엔티티 매니저 팩토리를 생성함- 시간이 오래걸림
- persistence.xml을 읽고, JPA를 동작시키기 위한 기반 객체를 만들고, JPA 구현체에 따라서는 DB 커넥션 풀도 생성함
 
 - 엔티티 매니저 팩토리는 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용해야 함
 
 
 - 엔티티 매니저 생성
EntityManager em = emf.createEntityManager();- 엔티티 매니저를 통해 엔티티를 데이터베이스에 등록/조회/수정/삭제 할 수 있음
 - 내부에 데이터베이스 커넥션을 유지하면서 데이터베이스와 통신함
 - 데이터베이스 커넥션과 밀접하기 때문에 스레드 간에 공유하거나 재사용하면 안됨
 - 엔티티 매니저 팩토리로부터 생성되고 JPA의 대부분의 기능을 제공함
 
 - 종료
em.close(); emf.close();- 사용이 끝난 엔티티 매니저는 반드시 종료(close) 해야함
 - 애플리케이션을 종료할 때 엔티티 매니저 팩토리도 반드시 종료(close) 해야함
 
 
4.2 트랜잭션 관리
JPA를 사용하면 항상 트랜잭션 안에서 데이터를 변경해야 함, 트랜잭션 없이 데이터 변경 시 예외 발생함
  EntityTransaction tx = em.getTransaction(); // 트랜잭션 API
  try{
    tx.begin();              // 트랜잭션 시작
    logic(em);
    tx.commit();             // 트랜잭션 커밋
  }catch(Eception e){
    tx.rollback();           // 예외 발생 시 트랜잭션 롤백
  }
위에처럼 엔티티 매니저(em)에서 트랜잭선 API(tx)를 받아와야 함
4.3 비즈니스 로직
엔티티 매니저를 이용해서 CRUD로 비즈니스 로직 구현하면 됨
- 등록(Create)
Member member = new Member(); member.setId(id); member.setUsername() em.persist(member);- JPA는 회원 엔티티의 매핑 정보(어노테이션(을 분석해서 다음과 같은 SQL을 만들어 쿼리해줌
 INSERT INTO MEMBER (ID, NAME) VALUES ('id1', 'name1')
 - 조회(Read)
// 한 건 조회 Member findMember = em.find(Member.class, id); // 목록 조회 List<Member> members = em.createQuery("select m from Member m", Member.class) .getResultList();find()메소드는 조회할 엔티티 타입(class)과 데이터베이스 기본 키와 매핑한 식별자 값(@Id)으로 엔티티 하나를 조회해줌JPQL을 사용해서 검색 조건을 특정할 수 있음
 - 수정(Update)
member.setName("newname");- 단순히 엔티티 객체의 값만 변경해줘도 DB에 아래와 같은 업데이트 쿼리를 알아서 해줌
 UPDATE MEMBER SET NAME="newname" WHERE ID="id1"
 - 삭제(Delete)
em.remove(member);- 엔티티 매니저의 
remove()메소드 호출을 통해 엔티티 삭제가 가능함 DELETE FROM MEMBER WHERE ID="id1
 
4.4 JPQL
위에 조회를 하는 코드 중 하나 이상의 회원을 조회할 때의 코드를 보면
// 목록 조회 List<Member> members = em.createQuery("select m from Member m", Member.class) .getResultList();- JPA를 사용하면 엔티티 객체 중심의 개발이 가장 큰 장점, 데이터베이스에 대한 처리는 JPA에게 맡겨야 함
 - 원래는 조회를 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색해야 함(컬렉션 사용하듯이)
 - 그러려면 테이블의 모든 엔티티들을 불러와서 엔티티 객체로 만들어야 검색이 가능해짐
 애플리케이션에서 필요로 하는 데이터만 불러오기 위해 결국 검색 조건이 포함된 SQL(=JPQL)을 사용해야 함
- JPQL?
- SQL을 추상화한 객체지향 쿼리 언어
 - SQL과 비슷한 문법을 가지며 SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 등 사용 가능
 - JPQL vs SQL
- JPQL운 엔티티 객체를 대상으로 쿼리, 즉 클래스와 필드를 대상으로 쿼리함
 - SQL은 데이터베이스 테이블을 대상으로 쿼리함
 
 - 위에 조회 코드에서 아래 SQL문 처럼 생긴 부분이 JPQL
 select m from Member m- 여기서 
Member는 엔티티 객체를 뜻하는 것이고, 데이터베이스의 MEMBER 테이블을 의미하는 것이 아님 - JPQL은 엔티티 객체를 대상으로 쿼리하는 것이기 때문에 데이터베이스 테이블과는 독립적
 - 사용 방법?
- 엔티티 매니저의 
createQuery(JPQL, Type)호출을 통해 쿼리 객체 생성 - 생성한 쿼리 객체의 
getResultList()메소드 호출 
 - 엔티티 매니저의 
 
 
