스프링 -JPA 강의 2회차

이진우·2023년 9월 16일
0

스프링 강의 요약

목록 보기
8/13

아래는 김영한 강사님의 스프링 JPA 를 듣고 정리한 내용이다.

JPA 표준

section1

JPA: 과거에는 객체를 데이터 베이스에 저장하려면 복잡한 JDBC,Mybatis,JDBC template 사용
이제는 JPA 라는 트랙터로 밀어버리면 된다(SQL없이)
  • 개발자는 SQL 매퍼이다. 매핑이란 객체랑 RDB를 연결하는 것
  • 데이터 베이스 테이블에는 상속관계가 없다
    풀 수 있는 방법:
    부모같은 테이블 만들고, 자식같은 테이블 만들어서 필요할 떄는 join 해서 가져오는 것
  • 슈퍼타입, 서브타입 관계
  • 객체는 참조로, 테이블은 외래키를 이용해서 JOIN 해서 다른 객체 및 테이블을 사용
  • JPA 필요성

    상속, 연관관계, 데이터 타입, 데이터 식별 방법 이 객체와 관계형 db의 차이점이 있다
    이 차이를 매꾸면서 객체를 자바 컬렉션 저장 하듯이 DB에 저장 하는 것이 JPA기술이다.

    ORM

    객체와 관계형 DB를 매핑하는 것.

    1차 캐쉬의 이점

    1) 모아서 보내는 것:Buffer Writing 기능
    2) 캐시: 조회할때 DB에서 가지고 오지 않고 쉽게 가져올 수 있다.
    3) 동일성 보장: 같은 데이터베이스 트랜잭션 안에서 동일성을 보장해 준다(==비교가 가능하다)

    Section2,3

    h2 데이터베이스

    DB에 따라서 SEQUENCE,AUTO INCREMENT 가 다른데 H2는 둘다 지원
    테스트 용도로 많이 쓴다.

    스프링에 맞는 JPA 를 찾으려면...

    spring.io->projects->spring boot->: 내가 사용하는 버젼과 Reference DOC에서 Dependency versions 에서 ORG.Hibernate 찾으면 어떤 버젼 사용하는지 나온다.

    쿼리 콘솔창에 보이기

  • show_sql: 쿼리 콘솔에 보이기
  • format_sql: 이쁘게 포맷팅 시켜줌
  • use_sql_comments:쿼리가 왜 나오는지 적어줌
  • JPA 구동 방식

    1)Persistence 가 persistence.xml 을 참고해서 EntityManagerFactor 를 생성한다
    2)필요할 떄마다 EntityManager 를 생성한다.

    EntityManagerFactory

    EntityManagerFactory는 애플리케이션 로딩시점에 딱 하나만 만들어 놔야 함

    Transaction

    JPA 에서는 데이터를 변경하는 모든 작업은 트랜잭션 안에서 작업해야 한다.
    Transaction은 한 개 이상의 데이터베이스 연산을 묶어서 하나의 작업으로 처리하는 것을 의미

    영속성 관리

  • 고객의 요청이 올떄마다 EntityManager 를 사용한다
  • 엔티티매니저는 DB커넥션을 사용한다.
  • 스프링 프레임워크 같은 컨테이너 환경에서는 엔티티 매니저와 영속성 컨텍스트가 N:1 이다
  • entityManager 안에 영속성 컨텍스트가 있다고 생각하자
  • em.persist()

  • em.persist는 DB에 저장을 의미하는게 아니라 엔티티를 영속화 한다는 뜻이다
  • em.persist(member)는 영속성 컨텍스트에서 멤버를 관리하게 하는 것이다. 아직 DB에 저장하지 않았고 transaction commit 시점에 쿼리를 보낸다 .
  • 영속성 컨텍스트의 이점

  • 1차 캐쉬: em.find 하면 먼저 1차 캐쉬를 조회한 후 없다면 DB로 select 쿼리를 날린다
  • 동일성 보장: 단 같은 transaction 안에서만
  • 트랜잭션을 지원하는 쓰기 지연: transaction.commit -> 축적한 후 한번에 보낸다. BATCHSIZE로 묶어서 보내기가 가능(Buffer 모아서 Writing 가능) 이렇게 하면 최적 화 할 수 있는 여지가 있다.
  • 변경 감지:데이터 베이스에서 객체를 찾아온 다음에 데이터의 값을 수정하면 자동으로 update 쿼리가 나간다. 그 방식은 트랜잭션 커밋 시점에 엔티티와 엔티티의 이전 초기 상태였던 스냅샷을 비교하여 변한게 있다면 그 때 쓰기 지연 저장소에 update 쿼리를 넣고 flush를 수행하는 식이다.
  • 엔티티를 삭제할 떄는?

    em.remove()로 가능하다.

    준영속상태?

    em.detach(member) 등으로 회원 엔티티를 영속성 컨텍스트에서 분리한 상태를 준영속 상태라고 한다 em.detach()를 트랜잭션이 커밋되기 전에 수행한다면 그 전에 수정이나 persist 마구마구 수행해도 전혀 바뀌지 않는다
    그렇다면 영속성 컨텍스트가 제공하는 기능(더티체킹) 을 사용하지 못한다.
  • 준영속상태로 만드는 방법
  • 1)em.detach(entity)
    2)em.clear()->영속성 컨텍스트를 완전 초기화
    3)em.close()

    플러쉬

    보통 데이터 베이스 트랜잭션이 커밋될 때 flush가 일어난다.
    플러쉬가 발생한다면
    1) 변경 감지 수행
    2) 수정된 엔티티를 쓰기 지연 SQL 저장소에 등록
    3) 쓰기 지연 SQL 저장소의 쿼리를 db에 전송한다.
  • 영속성 컨텍스트를 flush하는 법
  • 1)em.flush()
    2)트랜잭션 커밋
    3)JPQL 쿼리 실행
    3번은 그럴 수 밖에 없다. em.persist()를 하고 JPQL 을 실행하면 맥락상 persist 한게 들어갔다고 보는게 편리할 것 같기 때문이다
    em.flush()한다고 1차 캐쉬가 지워진다는 망상은 하지 말자!

    repository.save의 안에는

    실무에서 자주 사용하는 public interface MemberRepository extends JpaRepository<Member,Long>를 만들때에는 memberRepository.save(member);를 통해서 엔티티를 저장하는데 이 안에 내부적으로 살펴보면 내부적으로 SimpleJpaRepository가 빈등록이 되어서 아래 메서드를 호출 하여 저장하게 된다.

    @Transactional
    	@Override
    	public <S extends T> S save(S entity) {
    
    		Assert.notNull(entity, "Entity must not be null.");
    
    		if (entityInformation.isNew(entity)) {
    			em.persist(entity);
    			return entity;
    		} else {
    			return em.merge(entity);
    		}
    	}
    profile
    기록을 통해 실력을 쌓아가자

    0개의 댓글