SQL을 한땀한땀 작성하는 것은 개발 생산성이 떨어질 수 밖에 없다.
JPA⇒ 혁신
지금 시대는 객체를 관계형 DB에 관리
패러다임의 불일치
객체 vs 관계형 데이터베이스


SELECT M.*, T.*
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
public Member find(String memberId) {
//SQL 실행
Member member = new Member();
//데이터베이스에서 조회한 회원 관련 정보를 모두 입력
Team team = new Team();
//데이터베이스에서 조회한 팀 관련 정보를 모두 입력
//회원과 팀 관계 설정
member.setTeam(team);
return member;
}


객체답게 모델링 할수록 매핑 작업만 늘어난다.
객체를 자바 컬렉션에 저장 하듯이 DB에 저장할 수는 없을까?
⇒JPA
-Java Persistence API
-자바 진영의 ORM기술 표준



JPA 표준 구현체로 Hibernate를 사용한다
+패러다임 불일치란?
객체와 관계형 데이터베이스가 다르기 때문에 생기는 문제이다.
객체는 상속을 받지만 데이터베이스는 상속관계가 없다
이것을 해결하기 위해서 관계형 데이터베이스에서 조인을 사용하는 등
비용이 발생하는데 이런 과정이 모두 패러다임 불일치를 해결하는데
드는 비용이다.
jpa가 관리하는 객체 ⇒ 엔티티


SQL이 한번만 실행되고 그 다음에는 JPA가 들고 있는 메모리 상에서 반환을 해준다
⇒ SQL 한번만 실행
단, 같은 트랜잭션 안에서만 된다.


위 persist 3개를 모았다가 (커밋하기 전까지) 모아서 커밋한다.
⇒ 성능을 끌어올린다
JPA는 성능을 위해 지연 로딩과 즉시 로딩 두가지를 모두 지원한다
객체가 실제 사용될 때 로딩
Team 이 가끔 사용되는 경우

Member와 Team이 거의 같이 사용되는 경우

두 전략을 선택적으로 사용해서 성능 최적화를 고민해볼 수 있다.
study/h2/bin
h2.bat으로 실행(window)
H2 연결 에러 해결 참고
[H2] Database (디렉토리 경로) not found, either pre-create it or allow remote database creation
maven 프로젝트 생성(intellij)
hibernate.org
pom.xml 설정
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.3.10.Final</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
</dependency>
</dependencies>
EntityManagerFactory가 가지는 특징1. 엔티티 매니저 팩토리는 하나의 데이터베이스에 하나만 생성한다. (생성 비용이 비싸기 때문)
2. 엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전하다.
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
version="2.1">
<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"/>
<!-- 옵션 -->
<!-- 콘솔에 하이버네이트가 실행하는 SQL문 출력 -->
<property name="hibernate.show_sql" value="true"/>
<!-- SQL 출력 시 보기 쉽게 정렬 -->
<property name="hibernate.format_sql" value="true"/>
<!-- 쿼리 출력 시 주석(comments)도 함께 출력 -->
<property name="hibernate.use_sql_comments" value="true"/>
<!-- JPA 표준에 맞춘 새로운 키 생성 전략 사용 -->
<property name="hibernate.id.new_generator_mappings" value="true"/>
<!-- 애플리케이션 실행 시점에 데이터베이스 테이블 자동 생성 -->
<property name="hibernate.hbm2ddl.auto" value="create"/>
<!-- 이름 매핑 전략 설정 - 자바의 카멜 표기법을 테이블의 언더스코어 표기법으로 매핑
ex) lastModifiedDate -> last_modified_date -->
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
</properties>
</persistence-unit>
</persistence>
Persistence 가 persistence.xml을 읽어서 EntityManagerFactory에서 EntityManager를 찍어낸다
em.createQuery("select m from Member as m", Member.class).getResultList();
장점: 페이지네이션 시 limit을 설정할 수 있다.(setMaxResult(값))
문제는 검색 쿼리
애플리케이션이 필요한 데이터만 DB에서 불러오려면 Entity 객체를 쿼리 할 수 있어야 한다
JPQL은 엔티티 객체를 대상으로 쿼리
SQL은 데이터베이스 테이블 자체를 쿼리