JPA를 혼자 공부하는 것보다 다른 사람들과 같이 공부하면서 설명하는게 더 효과적이라 생각하여 진행한다.
JPA 스터디는 3명의 인원과 오프라인으로 매주 토요일 오전 10시에 진행한다
책은 자바 ORM 표준 JPA 프로그래밍 (저자: 김영한) 으로 진행하고 목표는 완독이다.
장소: 강남역 곤트란쉐리에
시간: 10:00 ~ 12:00
개발시 CRUD용 SQL의 반복이 너무 많음
JDBC: 여러 관계형 DB에 접속하여 자바와 DB 사이에 데이터를 주고받을 수 있도록 지원하는 표준 자바 응용 프로그래밍 인터페이스
JDBC API: SQL을 이용해 자바로 DB 응용 프로그래밍을 작성할 수 있도록 지원
JDBC API가 인터페이스만을 제공해주면 실질적인 구현은 DBMS 제조사들이 자신들의 DB에 맞게 구현하여 제공 -> 이를 JDBC 드라이버라고 함
즉, JDBC API를 사용하면 하나의 자바 응용 프로그램만으로 JDBC 드라이버를 제공하는 어떤 관계형 DBMS에도 접근이 가능한 것.
회원을 조회하는 기능을 개발한다 했을 때
회원 조회용 SQL을 작성
SELECT ID, NAME, AGE FROM MEMBER WHERE ID = ?
JDBC API를 사용해 SQL을 실행
executeQuery(sql)
조회 결과를 Member 객체로 매핑
String name = findMember.getString("NAME");
int age = findMember.getString("AGE");
Member member = new Member();
member.setName(name);
member.setAge(age);
1 ~ 3 과정을 기능을 추가할 때마다 계속 반복해야 한다
DB는 객체 구조와 다르기에 객체를 직접 DB에 저장하거나 조회할 수 없다
따라서 개발자가 중간에서 SQL과 JDBC API를 사용해 변환 작업을 해주어야 한다
jpa.persist(상속관계 있는 객체)
를 하게 되면 JPA가 상속에 맞게 조회 및 저장을 하게 된다객체는 참조를 사용해서 연관된 객체를 조회하고
테이블은 외래키를 사용해서 연관된 테이블을 조회한다
객체를 테이블에 맞게 모델링을 하게 되면 객체지향의 특징을 잃어버리게 된다
객체는 참조를 통해서 관계를 맺음
이때 개발자가 중간에서 변환 역할을 할 때 패러다임 불일치에 따라 해결을 위한 비용이 발생
JPA를 사용하면 이를 해결
member.setTeam(team) 회원과 팀 참조 관계
jpa.persist(member) 회원과 연관관계 함께 저장
객체에서 참조를 사용해 연관된 관계를 찾는 것을 객체 그래프 탐색이라고 한다
객체는 마음껏 객체 그래프를 탐색할 수 있다.
member.getOrder().getOrderItem()
반면 SQL을 직접 다루게 되면 할 수 없다. 처음 실행하는 SQL에 따라 탐색 범위가 정해지는데, 언제 객체 그래프가 끊어질지 모르기에 함부로 탐색할 수 없다.
JPA는 연관된 객체를 사용하는 시점에 적절한 SELECT SQL을 실행
-> 실제 객체를 사용하는 시점까지 DB조회를 미룬다고 해서 지연로딩 이라고 한다
getMember
로 member 객체를 호출 여러번 한다면 각각 다른 인스턴스가 된다 (new Member())결국 JPA는 패러다임 불일치 문제를 해결해주고, 정교한 객체 모델링을 유지하게 도와준다
용어정리
ORM: 객체와 관계형 DB를 매핑
ORM프레임워크를 사용하면, 단순히 SQL을 개발자 대신 생성해 DB에 전달 할 뿐만 아니라
패러다임 불일치 문제들도 해결
매핑 방법은 ORM 프레임워크에서 알려준다
자바 진영에서는 하이버네이트 프레임워크가 성숙한 ORM 프레임워크다
하이버네이트를 기반으로 자바 ORM 표준이 만들어진게 JPA다
JPA는 자바 ORM 기술에 대한 API 표준 명세다 (인터페이스를 모아둔것)
JPA를 사용하려면 JPA를 구현한 ORM 프레임워크를 선택해야 한다
jpa.persist(member)
처럼 JPA에게 객체를 전달만 하면 된다, 반복적인 일은 JPA가 해준다jpa.find(memberId)
를 여러번 해도 처음만 DB에 쿼리를 전달하고, 이후부터는 조회한 회원 객체를 재사용한다maven과 gradle의 차이
jpa가 성능적으로 좋지 않은 이유?
책에서는 maven 을 기준으로 설명을 진행
JPA는 META-INF/persistence.xml
을 사용해서 필요한 설정 정보를 관리
<persistence-unit name="jpabook">
// 앤티티 매니저 팩토리 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
// 앤티티 매니저 생성
EntityManager em = emf.createEntityManager();
// 트랜잭션 획득
EntityTransaction tx = em.getTransaction();
// 트랜잭션 시작
tx.begin();
// 트랜잭션 커밋
tx.commit();
// 앤티티 매니저 종료
em.close();
// 앤티티 매니저 팩토리 종료
emf.close();
Persistence
클래스가 META-INF/persistence.xml
설정 정보를 조회하여 앤티티 매니저 팩토리를 생성
앤티티 매니저 팩토리는 비용이 아주 크기 때문에, 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용해야 함
앤티티 매니저 팩토리에서 앤티티 매니저를 생성함
앤티티 매니저를 통해 앤티티를 데이터베이스에 CRUD 할 수 있음
JPQL은 앤티티 객체를 대상으로 쿼리함
SQL은 테이블을 대상으로 쿼리함
select M.ID, M.NAME, M.AGE from MEMBER M
자세한건 10장에서..
@PersistenceUnit
private EntityManagerFactory factory;
@PersistenceContext
private EntityManager em;
PersistenceContext 어노테이션을 통해 EntityManager를 빈으로 등록할 수 있음
이때 EntityManagerFactory에서 생성된 em을 생성하거나 기존의 em을 반환해준다
EntityManager는 여러 스레드가 동시에 접속하면 동시성 문제가 발생하여 공유해서는 안됨
PersistenceContext로 엔티티 매니저를 주입받아도 괜찮은 이유는
스프링 컨테이너가 초기화 되면서 EntityManager를 Proxy로 감싸는데
그리고 Proxy를 통해 EntityManager를 생성하여 thread-safe를 보장함 (이 부분은 아직 이해가 잘 안된다.. 왜 Proxy로 감싸면 스레드 safe를 보장하지??)
: 프록시.. 책 뒤편에 나온다고 한다!