[Inflearn] 자바 ORM 표준 JPA 프로그래밍 기본 - 김영한 https://www.inflearn.com/course/ORM-JPA-Basic
관계형 데이터베이스와 객체지향 환경에서 설계된 객체를 중간에서 연결해주는 프레임워크로 대중적인 언어 대부분에 ORM 기술이 존재함
자바 진영의 ORM 기술 표준으로 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스
- SQL 중심적인 개발에서 객체 중심으로 개발 가능하다.
- 간단한 메소드 사용으로 생산성이 증가한다.
- 유지보수가 편리하다.
- 객체와 RDBMS(관계형 데이터베이스)간의 패러다임 불일치 문제를 해결한다.
- 데이터 접근 추상화와 벤더 독립성을 보장한다.
- 1차 캐시와 동일성(identity) 보장을 보장한다.
트랜잭션을 지원하는 쓰기 지연 : JDBC Batch SQL 기능을 사용해 insert SQL 한번에 전송, update & delete로 인한 로우(row)락 시간 최소화
지연로딩(lazy loading) : 객체가 실제로 사용될 때 해당 객체 로딩
Hibernate는 Jpa의 구현체라고 할 수 있다.
Jpa는 데이터베이스와 자바 객체를 매핑하기 위한 인터페이스를 제공하고 하이버네이트는 이 인터페이스를 구현한 것이다.
개발자가 직접 쿼리를 작성하지 않아도 하이버네이트가 지원하는 메소드 내에서 JDBC API가 동작한다(개발자가 직접 JDBC API를 사용하는 것은 아님).
하지만 특정 데이터베이스에 종속되지 않음으로 특정 데이터베이스에만 종속되는 함수는 사용할 수 없다.
그 외에 EclipseLink, DataNucleus, OpenJPA, TopLink Essentials 등이 있다.
Jpa를 쉽게 사용하기 위해 스프링에서 제공하고 있는 프레임워크이자 Jpa를 한 단계 더 추상화시킨 인터페이스이다.
JpaRepository를 구현하며 Repository 내부적으로 entity manager를 사용하여 동작한다.
findByXX등 자주 사용하는 메서드를 쉽게 사용할 수 있있다.
* Spring data jpa 사용할 것을 권장
엔티티를 영구 저장하는 환경이라는 뜻으로 애플리케이션과 데이터베이스 사이 객체를 보관하는 가상의 데이터베이스 같은 역할
엔티티 매니저를 통해 영속성 컨텍스트에 접근하여 엔티티를 보관하고 관리
비영속 - 객체를 단순히 생성한 상태
Member member = new Member();
member.setId("member1");
member.setName("memberA");
영속
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(member);
- 엔티티가 영속성 컨텍스트에 저장되어 영속성 컨텍스트에 의해 관리되는 상태
- 영속 상태가 되었다고 해서(persist()를 하였다고 해서) 데이터베이스에 바로 반영되는 것은 아님
- 트랜잭션의 커밋 시점에서 영속성 컨텍스트에 있는 정보들이 데이터베이스에 쿼리로 실행됨
준영속 - 영속성 컨텍스트에서 분리
em.detach(member);
삭제 - 삭제의 경우 데이터베이스에도 커밋 후 반영됨
em.remove(member);
1. 동일한 트랜잭션 안에서 1차 캐시
영속성 컨텍스트 내부에는 1차 캐시가 존재하여 영속성 컨텍스트에 저장되는 순간 1차 캐시에도 저장되고 find 메서드가 호출될 때 1차 캐시부터 조회한다.
1차 캐시에 존재하면 바로 조회(데이터베이스 조회x) 가능하지만 없으면 데이터베이스를 조회한다.
Key는 @Id로 선언한 값, Value는 해당 객체 자체
Member member = new Member();
member.setId("member1");
member.setUsername("memberA");
// 1차 캐시에 저장
em.persist(member);
// 1차 캐시에서 조회
Member findMember = em.find(Member.class, "Member1");
// 데이터베이스에서 조회
Member findMember = em.find(Member.class, "Member2");
2. 동일성(Identity) 보장
영속 엔티티의 동일성을 보장한다.
1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을 DB가 아닌 애플리케이션 차원에서 제공한다.
Member a = em.find(Member.class, "Member1");
Member b = em.find(Member.class, "Member1");
Systen.out.println(a == b); // true
같은 아이디로 두 번 조회했을 시 다른 객체가 아닌 같은 레퍼런스가 조회된다.
3. 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
// 반드시 트랜잭션을 시작해야함
transaction.begin();
em.persist(memberA);
em.persist(memberB);
// 아직 쿼리를 날리지 않음
// 커밋 시점에 데이터베이스에 쿼리 보냄
transaction.commit();
영속성 컨텍스트와 1차 캐시에 엔티티를 저장하고 해당 쿼리를 생성하여 SQL 저장소에 저장한다.
데이터베이스에 해당 쿼리를 실행한다.
4. 변경 감지(Dirty Checking)
엔티티의 변경사항을 감지하여 수정한다.
Member memberA = em.find(Member.class, "member1");
// 영속 엔티티 수정
memberA.setName("nj");
memberA.setAge(27);
따로 update에 대한 메서드가 없이 set으로 변경사항 수정
영속성 컨텍스트 1차 캐시에 저장된 내용과 비교하여 update 쿼리를 자동으로 생성한다.
영속성 컨텍스트의 변경사항을 바로 데이터베이스에 반영하여 영속성 컨텍스트에서 분리하면 준영속 상태가 된다.
영속성 컨텍스트가 제공하는 기능을 사용하지 못하지만 영속성 컨텍스트를 비우는 것은 아니다.
영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화한다.
*트랜잭션이라는 작업 단위가 중요 → 커밋 직전에만 동기화 시키면 됨
영속성 컨텍스트를 플러시하는 방법 (1) 직접 호출
em.flush();
(2) 트랜잭션 커밋
transactin.commit();
(3) JPQL 쿼리 실행
em.persist(memberA);
em.persist(memberA);
em.persist(memberA);
// 중간에 JPQL 실행
query = em.createQuery("select m from Member m", Member.class);
List<Member> members = query.getResultList();
플러시 모드 옵션
// 커밋이나 쿼리 실행할 때 플러시(기본값)
em.setFlushMode(FlushModeType.AUTO);
// 커밋할 때만 플러시
em.setFlushMode(FlushModeType.COMMIT);
준영속 상태로 만드는 방법
// 특정 엔티티만 준영속 상태로 전환
em.detach(entity);
// 영속성 컨텍스트 초기화
em.clear();
// 영속성 컨텍스트 종료
em.close();
[SPRING] JPA 프로그래밍 기본 | 객체지향 쿼리 언어 (0) | 2021.04.08 |
---|---|
[SPRING] JPA 프로그래밍 기본 | 값 타입 (0) | 2021.04.08 |
[SPRING] JPA 프로그래밍 기본 | 프록시와 지연로딩 (0) | 2021.03.11 |
[SPRING] JPA 프로그래밍 기본 | 상속 (0) | 2021.03.09 |
[SPRING] JPA 프로그래밍 기본 | 연관관계 (0) | 2021.03.09 |
댓글 영역