h2 DB 설치 (http://www.h2database.com/)
chmod 755 h2.shh2.bat 입력 ((mac) ./h2.sh 입력) ⇒ 브라우저로 연동 ⇒ 무언가 뜨지 않을 경우 : IP 주소만 localhost로 변경 (ex) http://xxx.xxx.xxx.xxx:8082/ ⇒ http://localhost:8082/)Maven
프로젝트
groubId : jpa-basic
artifactId : ex1-hello-jpa
의존성 추가
<dependencies>
<!-- JPA 하이버네이트 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.3.10.Final</version>
</dependency>
<!-- H2 데이터베이스 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
</dependency>
</dependencies>
JPA 설정 - persistence.xml
JPA 설정 파일
/META-INF/persistence.xml 위치
persistence-unit name으로 이름 지정
javax.persistence로 시작: JPA 표준 속성
hibernate로 시작: 하이버네이트 전용 속성
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="hello">
<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.hbm2ddl.auto" value="create" />-->
</properties>
</persistence-unit>
</persistence>
데이터베이스 방언(Dialect)
JPA는 특정 DB에 종속 X
DB 별 제공하는 SQL 문법과 함수는 조금씩 다르다
방언(Dialect) : SQL 표준을 지키지 않는 특정 데이터베이스만의 고유 기능

hibernate.dialect 속성에 지정
JPA 구동 방식

실습 (항상 H2 Database 켜놓기)
0) h2 database 설정은 직전에 설정한 persistence.xml과 동일하게 설정
1) Pesistence 등록 (패키지 & 클래스 네임 확인)
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
//code
em.close();
emf.close();
}
}
2) 객체 & 테이블 생성, 매핑
객체(Java)
package hellojpa;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
//@Table(name = "USER") // 테이블 이름 매핑! 없으면 클래스 명과 같은 테이블과 매핑되는 관례를 따른다.
public class Member {
@Id
private Long id;
//@Column(name = "username") // 컬럼 이름 매핑! 없으면 필드 명과 같은 컴럼과 매핑되는 관례를 따른다.
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
테이블(H2)
create table Member (
id bigint not null,
name varchar(255),
primary key (id)
);
3) 주의할 점(특징)
❗4) 데이터 삽입
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member member = new Member();
member.setId(1L);
member.setName("HelloA");
em.persist(member);
tx.commit();
} catch (Exception e){
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
💥애플리케이션 실행 시, 클래스를 찾지 못하는 오류가 발견 되면 아래와 같은 의존성을 주입하자.
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
삽입 결과

❗5) 데이터 조회
try {
Member findMember = em.find(Member.class, 1L);
System.out.println("findMember.id = " + findMember.getId()); //sql
System.out.println("findMember.name = " + findMember.getName()); //영속성 컨텍스트
tx.commit();
}
조회 결과
//print:
Hibernate:
select
member0_.id as id1_0_0_,
member0_.name as name2_0_0_
from
Member member0_
where
member0_.id=?
findMember.id = 1
findMember.name = HelloA
❗6) 데이터 삭제
try {
Member findMember = em.find(Member.class, 1L);
em.remove(findMember);
tx.commit();
}
❗7) 데이터 수정
try {
Member findMember = em.find(Member.class, 1L);
findMember.setName("HelloJPA");
tx.commit();
}
em.persist(findMemver)저장하는 문장 필요 x ⇒ Why? JPA를 통해 가져온 Entity는 JPA가 관리를 하고, 트랜잭션을 커밋하는 시점에 변경을 다 체크한다. (= 알아서 update 커밋) ⇒ 🧨변경 감지
결과

JPQL
Java Persistence Query Language : 객체 지향 쿼리 (방언에 맞도록 변화한다.)
전체 조회
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
List<Member> result = em.createQuery("select m from Member as m", Member.class).getResultList();
for (Member member : result) {
System.out.println("member.name = " + member.getName());
}
tx.commit();
} catch (Exception e){
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
결과
Hibernate:
/* select
m
from
Member as m */ select
member0_.id as id1_0_,
member0_.name as name2_0_
from
Member member0_
member.name = HelloJPA
member.name = HelloB
페이징 (offset, limit 설정)
try {
List<Member> result = em.createQuery("select m from Member as m", Member.class)
.setFirstResult(5)
.setMaxResults(8)
.getResultList();
for (Member member : result) {
System.out.println("member.name = " + member.getName());
}
tx.commit();
}
조건 조회
try {
List<Member> result = em.createQuery("select m from Member as m where m.id >= 2", Member.class)
.getResultList();
for (Member member : result) {
System.out.println("member.name = " + member.getName());
}
tx.commit();
}
where를 사용JPA를 사용하면 엔티티 객체 중심으로 개발, 문제는 필터링을 통한 검색 쿼리 ⇒ JPQL
JPQL ⇒ 엔티티 객체를 대상으로 쿼리
SQL ⇒ DB 테이블을 대상으로 쿼리