Spring Data Jpa

임정택·2021년 3월 30일
0

개념

영속성(Persistence): 데이터를 생성한 프로그램이 종료되더라도 사라지지 않는 데이터의 특성을 얘기 한다.
jpa(java persistence api) : 즉, JPA는 ORM을 사용하기 위한 표준 인터페이스를 모아둔 것이다. 사용자가 원하는 jpa구현체를 선택해서 사용하면 되는데 hibernate로 사용한다.

ORM은 Object Relational Model로 다음과 같은 기능을 담당한다.

  • DB테이블과 객체를 매핑
  • ORM은 DB테이블과 객체 간의 관계를 바탕으로 자동으로 SQL을 생성해 준다.
  • ORM은 관계형 데이터베이스의 ‘관계’를 Object에 반영하자는 것이 목적이다.

하이버네이트 프레임워크(ORM FrameWork)는

  • 데이터베이스와 응용 프로그램 사이에 레이어를 만든다.
  • 데이터베이스 연결 문자열, 엔터티 클래스, 매핑 등의 구성 정보를 로드
  • 애플리케이션과 데이터베이스 간의 데이터를 동기화하는 영속 객체를 생성
  • Hibernate는 Repository계층을 관리함으로서 객체 지향적으로 데이터를 관리하게 되어. 개발자가 비지니스 로직에 집중 할 수 있는 환경을 제공한다.

사용자 어플리케이션에서 세션 팩토리에 세션을 요청하면 세션 팩토리가 설정파일(configuragtion)을 참고하여 Session Object를 인스터화하여 반환해주면. 세션오브젝트를 이용해 디비와 상호연결을 한다. 세션은 매번 디비와 물리적연결이 필요할떄 생성되어서 persistent object를 저장하고 되찾는데 사용한뒤에 없어진다.

흐름

  1. JPA는 Persistence.xml파일을 로딩함
  2. 파일에는 영속성 유닛이 설정되어 있는데 이게 JPA가 연동할 DB에 대한 정보가 들어있음
  3. 이 영속성 유닛 설정정보를 바탕으로 EntityManagerFactory 객체를 생성함
  4. ENntityManagerFactory 로부터 EntityManager를 생성하여 DB에 저장

Persistence Context(영속성 컨텍스트)

Entity Manager(동일하게 생각)를 생성할떄 자동으로 만들어지는데, 엔티티객체들을 관맇는 컨테이너, EntityManager를 통해서만 접근이 가능하며 영속성 컨텍스트에 등록된 엔티티는 ENtityManager가 제공하는 메소드를 통해 관리됨

  • 상태

    • 비영속(new): 영속성컨텍스트와 무관한 상태
    • 영속(Managed): 저장된 상태
    • 준영속(Detached): 한번 저장되었다가 분리된 상태
    • 삭제(Removed): 삭제된 상태
  • 1차캐시와 FLUSH

    EntityManager 의 persist를 통해 엔티티를 영속화 시키면, 엔티티는 (key,Entity)형태로 1차캐시에 등록된다.
    1차캐시에 저장된 엔티티는 바로 실제 데이터베이스에 연동되지않고 트랜잭션을 종료할때 실제 디비에 반영된다. (이떄서야 디비에 INSERT문이 실행됨)

이런 영속성 컨텍스트에 저장된 엔티티를 디비에 반영하는 과정을 FLUSH 라 함

  • SQL 저장소

    엔티티를 영속화시키면 먼저 영속성컨텍스트에 등록된다음 해당 엔티티에 해당하는 SQL문을 생성하여 SQL 저장소에 등록한다.

    항상 유의할것은 다음이다

조회 및 CRUD기능 등 엔티티와 관련된 작업을 처리하기 하기위해서 엔티티를 반드시 영속성컨텍스에 영속화시켜놓아야 그 후에 작업을 처리해아한다는것이다.

  • 스냅샷

    엔티티를 영속화시키면 복사본을 만들어서 별도의 컬렉션에 저장하는데 이 공간을 스냅샷이라 한다.

    스냅샷에 저장된 원래 엔티티와 1차 캐시에 수정된 엔티티를 비교해서 변경된 값을 UPDATE쿼리문으로 만들어 전송한다. 전송시기는 트랜잭션이 종료될때이다.

    이떄, 모든필드수정전략을 사용하는데 이는 다음과 같은 이유여서다.

    1. 애플리케이션 로딩 시점에 수정쿼리를 미리 생성해두고 재사용가능( 수정쿼리가 항상 같으니)
    2. DB에 동일한 쿼리보내면 이전에 파싱한 쿼리를 재사용한거이므록

    하지만 단순 조회만을 위해 스냅샷(instance)를 만들게 되면 더 많은 메모리를 사용하는 단점이 있다.
    대량의 데이터를 조회만 할거기 때문에 읽기 전용로 메모리 사용량을 최적화할 수 있다.

    @Transactional(readOnly = true)

    해당 옵션을 주면 Spring Framework가 Hibernate Session의 Flush 모드를 Manual로 설정하여,
    강제로 flush()를 하지 않는 한 flush()가 일어나지 않는다.
    트랜잭션이 커밋되어도 플러시되지 않음
    flush() 할 때 일어나는 스냅샷 비교와 같은 무거운 로직을 수행하지 않음 -> 성능 향상
    트랜잭션 시작, 로직수행, 커밋은 똑같이 동작한다.

  • CRUD

    실질적인 CRUD 기능은 EntityManageFactory 부터 생성된 EntityManager를 얻어 이 객체의 persist 메소드를 이용하여 엔티티에 설정된 값을 테이블에 저장함

하지만 이렇다고 실제 DB에 반영되는 것이 아니다.

실제 테이블에 저장되려면 해당 작업(CRUD)이 반드시 트랜잭션I최소작업단위) 안에서 수행되어야한다.
(Transaction은 EntityManager로부터 생성될수 있으며, 트랜잭션시작코드는 begin, commit(성공), 실패(rollback)으로 나눠짐

  • Entity Annotation
    • Column : 속성(nullable.)
    • Entity
    • Table
    • Temporal : 날짜 데이터를 매핑할떄 사용
    • Transient : 임시로 사용되는 변수들은 아예 매핑에서 제외하는 경우에 사용(영속필드에서 제외)

쿼리

JPQL(Java Persistence Query Language) → 검색대상이 엔티티임 ,SQL과 매우 유사

  1. 기본 쿼리

    1. find + 엔티티 이름 + by 변수 이름
    2. findBy +변수이름
  2. Containing 키워드(Like 연산자 in sql)

    게시글 내용에 특정 단어가 포함된 글 목록을 조회하기 위해서 다음과 같이 사용함

    List<Board> findByContentContaining(String searchKeyword)
    List<Board> findByTitleContainingOrContentContaining(String , String);

    실제 처리되는 SQL문

    The LIKE operator is used in a WHERE clause to search for a specified pattern in a column.

    SELECT column1, column2, ...
    FROM table_name
    WHERE columnN LIKE pattern;

    Like 연산자에 대해 더 궁금하면 일단 https://www.w3schools.com/sql/sql_like.asp 여기로

  3. 데이터 정렬

    OrderBy + 변수 + Asc or Desc

    List<Board> findByTitleContainingOrderBySeqDesc(String seachKeyword)
  4. 페이징과 정렬 처리하기

    • 페이징과 정렬

      Pageable paging = PageRequest.of(0,5,Sort.Direction.DESC,"seq")
      (페이지번호, 검색할 데이터개수, 정렬 방향, 정렬대상이되는 변수(속성)이름)
  5. Page타입 사용하기

    Page<Board> pageInfo = boardReop.findByTitleContaing(String, paging)
    pageInfo의 함수들
    getSize => pagesize를 알 수 이음
    getTotalPages => page개수
    getTotalElements = > total count 
    nextPageable => 다음 page 객체 반환
    List<Board> boardList = pageInfo.getContent();
profile
안경 쓴 개발자

0개의 댓글