처음부터 엔티티 매핑 섹션까지 정리
JPA는 특정 데이터베이스에 종속되지 않는다.
JPA 구동 방식
- 설정 정보 조회
- EntityManagerFactory 생성
- EntityManager들을 생성
EntityManagerFactory emf=Persistence.createEntityManagerFactory("hello");
EntityManager em=emf.createEntityManager();
EntityTransaction tx=em.getTransaction();
tx.begin();
tx.commit();
em.close;
emf.close;
모드 데이터 변경은 Transaction 안에서 진행
- 엔티티 매니저 팩토리: 하나만 생성해서 애플리케이션 전체에서 공유
- 엔티티 매니저는 쓰레드간에 공유하지 않음. 사용하고 버리기
- 🧨🧨JPA의 모든 데이터 변경은 트랜잭션 안에서 실행
JPQL
- JPA를 사용하면 엔티티 객체를 중심으로 개발
- JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공
- JPQL은 엔티티 객체를 대상으로 쿼리
- SQL은 데이터베이스 테이블을 대상으로 쿼리
JPA에서 가장 중요한 2가지🎈
- 객체와 관계형 데이터베이스 매핑하기(Object Relation Mapping)
- 영속성 컨텍스트
영속성 컨텍스트
- JPA를 이해하는데 가장 중요한 용어
- 엔티티를 영구 저장하는 환경
- EntityManager.persist(entity)
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근
비영속 상태
영속 상태
Member member=new Member();
member.setId(100L);
member.setName("HelloJPA")
em.persist(member);
영속 상태가 된다고 DB에 쿼리가 바로 날라가는 것이 아니라
commit을 해야 DB에 저장이 된다.
영속성 컨텍스트의 이점
- 1차 캐시
- 동일성 보장
- 트랜잭션을 지원하는 쓰기 지연
- 변경 감지
- 지연 로딩
1차 캐시는 한 Transaction안에서의 효과가 있기 때문에 괸장히 찰나이며 큰 이득은 없다.
한번 조회한 후 또 조회하면 두번째 부터는 쿼리가 나가지 않고 캐시를 이용하여 조회한다.(한 트랜잭션 안에서)
이 부분에서 처음에는 DB select 쿼리가 나가고 이 값은 캐시에 저장되므로
두번째 find에서는 select 쿼리가 나오기 않는다.
조회를 했는데 1차 캐시에 없으면 DB에서 조회하고 1차 캐시에 저장을 하고 반환을 해준다.
영속 엔티티의 동일성 보장 (같은 트랜젝션 안에서)
- ==비교에서 똑같은 것 처럼
- 자바 컬렉션에서 가져왔을때 주소가 같은 것처럼 == 비교로 동일성을 보장한다.
엔티티 등록할 때 트랜잭션을 지원하는 쓰기 지연
커밋 했을 때 DB로 insetSQL을 보냄.
엔티티 수정, 변경 감지(dirty checking)
- 변경 후에 persist하지 않아도 됨📌📌
- java Collection과 비슷한 개념
- em.update와 같은 코드가 없어도 됨
플러시
- 영속성 컨텍스트의 변경내용을 데이터베이스에 반영
- 영속성 컨텍스트의 쿼리들을 DB에 날려줌
- commit 되면 플러시가 자동으로
- 변경 감지
- 수정된 엔티티를 쓰지 지연 SQL 저장소에 등록
- 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송(등록, 수정, 삭제 쿼리)
영속성 컨텍스트를 플러시하는 방법
- em.flush(): 직접/강제 호출(test 할때 유용), commit 전에 쿼리 나감.
플러시를 해도 영속성 컨텍스트 유지
- 트랜잭션 커밋: 플러시 자동 호출
- JPQL 쿼리 실행: 플러시 자동 호출
플러시 실행 옵션
- commit && 쿼리 날릴때 실행(기본값): FlushModeType.AUTO
- commit할 때만 플러시: FlushModeType.COMMIT
- AUTO로 손대지말고 쓰는 것을 권장
플러시는
- 영속성 컨텍스트를 비우지 않음
- 영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화
- 트랜잭션이라는 작업 단위가 중요-> 커밋 직전에만 동기화
준영속 상태
- 영속 상태의 엔티티가 영속성 컨텍스트에서 분리
- 영속성 컨텍스트가 제공하는 기능(dirty checking) 사용 못함
- 준영속 상태로 만드는 법
em.detach()
Memeber member=em.find(Member.class,10L);
member.setName("aaa");
em.detach(member);
tx.commit();
이때 select쿼리는 나가고 update쿼리는 나가지 않음.
준영속 상태이기 때문에 변경감지 기능을 하지 않음
- 특정엔티티만 준영속 상태로 전환: em.detach()
- em.clear(): 영속성 컨텍스트 전체 초기화
- em.close(): 영속성 컨텍스트를 종료
@Entity
- @Entity가 붙은 class는 JPA가 관리
- 기본 생성자 필수(파라미터가 없는 public/protected 생성자)
- final, enum, interface, inner 클래스 사용 X
- 저장할 필드에 final 사용 X
데이터베이스 스키마 자동 생성
- DDL을 애플리케이션 실행 시점에 자동 생성
- 테이블 중심-> 객체 중심
- DDL은 개발 장비에서만 사용
- 생성된 DDL은 운영 서버에서 사용하지 않거나 적절히 다듬은 후 사용
create, create-drop, update, validate, none
- 운영 장비에서는 절대 create, create-drop, update를 사용하면 안됨
- 개발 초기 단계는
create/update
- 테스트 서버는
update/validate
- 스테이징과 운영 서버는
validate/none
DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다.
매핑 어노테이션
- @Column
- @Temporal: 날짜
- @Enumerated: enum
- @Lob: BLOB,CLOB
- @Transient: 특정 필드를 컬럼에 매핑하고 싶지 않을때
@Enumerated
주의!🎈 ORDINAL 사용 X, 💥STRING💥만을 사용하자
EnumType.STRING
: 이름을 데이터베이스에 저장