
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;
}

Member class 자체에서 어노테이션을 통해 매핑 정보를 표시해주면 된다.
@Entity@Entity가 사용된 클래스를 엔티티 클래스라 한다.@Table@Id@Columnmapping이 필요없는 필드는 그냥 작성해주면 된다.
<?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" />
<!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
</properties>
</persistence-unit>
</persistence>
<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"/>
...
JPA는 특정 DB에 종속적이지 않은 기술이다. 그러므로 다른 DB로 쉽게 교체가능하다.
DB마다 SQL문법, 함수가 조금씩 다르다는 문제점이 존재한다.
ex
이러한 방언을 해결하기 위해 하이버네이트를 포함한 대부분의 JPA 구현체들은 다양한 DB 방언 클래스를 제공한다.

hibernate.dialect속성을 org.hibernate.dialect.H2Dialect로 설정하면 된다.
package jpabook.start;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.Persistence;
public class JpaMain {
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(); // 엔티티 매니저 팩토리 - 종료
}
}
코드는 크게 3부분으로 나뉘어 있다.
- 엔티티 매니저 설정
- 트랜잭션 관리
- 비즈니스 로직

EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
EntityManager em = emf.createEntityManager();
em.close();emf.close();JPA를 사용하면 항상 트랜잭션 안에서 데이터를 변경해야 한다.
`
EntityTransaction tx = em.getTransaction();
try{
tx.begin(); // 트랙잭션 - 시작
logic(em); //비즈니스 로직 실행
tx.commit(); //트랜잭션 - 커밋
} catch (Exception e){
tx.rollback();
}
`
트랜잭션 API를 이용해 비즈니스 로직이 정상 동작하면 트랜잭션을 커밋, 예외발생시 트랜잭션 롤백
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);
}
String id = "id1";
Member member = new Member();
member.setId(id);
member.setUsername("지한");
member.setAge(2);
//등록
em.persist(member);
```
- 엔티티를 저장하기 위해 em의 `persist()` 메소드에 저장할 엔티티를 넘겨주면 된다.
- JPA는 회원 엔티티의 매핑정보를 분석해서 SQL을 만들어서 DB에 전달한다.
##### 수정
`
member.setAge(20);
`
- 단순히 엔티티 값만 변경했다. JPA는 어떤 엔티티가 변경됐는지 추적하는 기능을 갖추고 있다.
- 엔티티 값만 변경하면 UPDATE SQL 생성 후 DB 값을 변경한다.
##### 삭제
`
em.remove(member);
`
- 엔티티 매니저의 `remove()` 메소드에 삭제하려는 엔티티를 넘겨준다.
- JPA는 다음 DELETE SQL 생성 후 실행한다.
##### 한 건 조회
`
Member findMember = em.find(Member.class, id);
`
- `find()`메소드는 조회할 엔티티 타입과 @Id로 DB Table의 기본 key와 매핑한 식별자 값으로 엔티티 하나를 조회한다.
##### 여러건조회 (JPQL)
```java
TypedQuery<Member> query =
em.createQuery("select m from Member m", Member.class);
List<Member> members = query.getResultList();
```
- JPA를 사용하면 개발자는 엔티티 객체 중심으로 개발하고 DB에 대한 처리는 JPA에게 맡긴다. 등록, 수정, 삭제에서는 SQL 전혀 사용하지 않았다. 문제는 **검색쿼리**!!
- JPA는 엔티티 객체 중심으로 개바하기 때문에 검색할 때도 테이블이 아닌 엔티티 객체 대상으로 검색해야한다.
- 검색 조건이 포함된 SQL을 사용해야하기 때문에 **JQPL(java persistence query language)** 쿼리 언어를 통해 문제를 해결한다.
###### JQPL
- SQL을 추상화한 객체지향 쿼리 언어
- SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 등 사용 가능
- 차이점
- JPQL : 엔티티 객체 대상 쿼리 (클래스와 필드 대상)
- SQL : 데이터베이스 테이블 대상 쿼리
- `from Member`에서 `MEMBER`테이블이 아닌 회원 엔티티 객체를 말하는 것이다.
> JPQL은 데이터베이스 테이블을 전혀 알지 못한다.
- `em.createQuery(JPQL, 반환타입)`을 실행해서 쿼리 객체 생성 후 쿼리객체의 `getResultList()`메소드 호출