본문 바로가기
카테고리 없음

JPA

by moonstal 2022. 7. 3.

JPA

영속성 관리

  • EntityManager Factory(1)-> EntityManager(N) 생성-> PersistenceContext(1) 커넥션풀-> db
  • 엔티티 생명주기: 비영속(new),영속(persist,merge),준영속(detach,clear,close),삭제(remove)
  • 이점:1차 캐시,동일성(같은 트랜잭션 안),쓰기 지연,변경 감지(엔티티와 스냅샷 비교),지연 로딩
  • 플러시: 직접flush,트랜잭션 커밋,JPQL 쿼리 실행, 옵션 setFlushMode(FlushModeType.COMMIT/AUTO)

엔티티 매핑

  • 객체와 테이블 매핑:
    • @Entity(기본 생성자 필수),
    • @Table(name,catalog,schema,uniqueConstraints)
  • 필드와 컬럼 매핑:

    • @Column((name = "name", nullable = false, length = 10)
    • @Enumerated(EnumType.STRING): enum
    • @Lob:CLOB(문자),BLOB(나머지)
    • @Transient: db x
  • 기본 키 매핑:

    • @Id @GeneratedValue :Long형 + 대체키 + 키 생성전략
    • (strategy = GenerationType.IDENTITY/SEQUENCE/TABLE)

연관관계 매핑

  • 단방향

      Member
      @ManyToOne
      @JoinColumn(name = "TEAM_ID")
      private Team team;
    
      member.setTeam(team);
  • 양방향 연관관계 주인

      Team에 추가
      @OneToMany(mappedBy = "team")//주인x , 읽기만
      List<Member> members = new ArrayList<Member>();
    
      findTeam.getMembers().size(); 
  • 객체와 테이블 차이
    • 객체: 멤버에 팀, 팀에 멤버스->사실상 단방향 2개
    • 테이블: 멤버에 팀id fk->외래키로 조인o
  • 연관관계 주인: 외래키 관리, 등록수정
  • 주인x: 읽기만, mappedBy
  • 주의: 양방향 매핑시 항상 양쪽다 값을 입력(연관관계 편의 메소드), 무한 루프 조심

다양한 연관관계 매핑

  • 다대일 단방향: 다(N) 연관관계의 주인
  • 일대다 단방향: 일(1)이 연관관계의 주인<->테이블:다(N) 쪽에 외래 키

고급 매핑

  • 상속관계 매핑: @Inheritance(strategy=InheritanceType.XXX)
    • 각각 테이블로 변환 -> 조인 전략 JOINED
    • 통합 테이블로 변환 -> 단일 테이블 전략 SINGLE_TABLE

    - @DiscriminatorColumn(name=“DTYPE”)
    - @DiscriminatorValue(“XXX”)

    • 서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략 TABLE_PER_CLASS

  • @MappedSuperclass: 공통 매핑 정보(ex.id,name)

프록시와 연관관계 관리

  • 프록시: em.getReference() 가짜 엔티티 객체 조회, 실제 클래스>프록시
  • 프록시 초기화 -> 프록시 통해 실제 엔티티 접근
  • 즉시 로딩과 지연 로딩:
  • 지연 로딩: @ManyToOne(fetch = FetchType.LAZY) 프록시로 조회 -> 사용 시점에 초기화 member.getTeam().getName();
  • 즉시 로딩: JPQL에서 N+1 문제, 사용x->fetch 조인, 엔티티 그래프
  • 영속성 전이: CASCADE, 연관 엔티티 함께(부모->자식)
  • @OneToMany(mappedBy="parent", cascade=CascadeType.PERSIST)
  • 고아 객체 제거: 연관관계 끊어진 자식 삭제 orphanRemoval = true(CascadeType.REMOVE)
  • 부모 엔티티 통해 자식 생명주기 관리

값 타입

  • 엔티티 타입: @Entity, 식별자로 추적 가능
  • 값 타입: 단순 값-자바 기본 타입/객체, 식별자x 추적 불가, equals 비교
    • 임베디드 타입: @Embeddable(정의),@Embedded(사용),기본 생성자,엔티티에 생명주기 의존, 공유 위험->복사해서 사용, 불변 객체로 설계(생성자)
    • 값 타입 컬렉션: 값 타입 하나 이상, 별도의 테이블, 변경 사항->다 삭제하고 다시 저장-> 대안: 일대다 관계

객체지향 쿼리 언어(JPQL)

소개

  • JPQL은 엔티티 객체를 대상으로 쿼리
      String jpql = "select m From Member m where m.name like ‘%hello%'"; 
      List<Member> result = em.createQuery(jpql, Member.class)
                              .getResultList();
  • QueryDSL: 자바코드
      JPAFactoryQuery query = new JPAQueryFactory(em);
      QMember m = QMember.member; 
      List<Member> list = query.selectFrom(m)
                              .where(m.age.gt(18)) 
                              .orderBy(m.name.desc())
                              .fetch();
  • 네이티브 SQL
      em.createNativeQuery(sql, Member.class).getResultList();

JPQL - 기본 문법과 기능

  • TypeQuery: 반환 타입 명확 <-> Query: 명확 x
  • getResultList():결과 하나 이상(List) <-> getSingleResult():결과 정확히 하나(단일 객체,결과하나x->예외)
  • 파라미터 바인딩: :username<-setParameter("username", usernameParam);
  • DTO로 바로 조회: SELECT new jpabook.jpql.UserDTO(m.username, m.age) FROM
    Member m
  • 페이징
      em.createQuery(jpql, Member.class)
      .setFirstResult(10)//조회 시작 위치
      .setMaxResults(20)//조회할 데이터 수
      .getResultList();
  • 조인
      SELECT m, t FROM Member m LEFT JOIN m.team t on t.name = 'A'

JPQL - 경로 표현식

  • .(점) 찍어 객체 그래프 탐색

  • 상태 필드: m.username

  • 단일 값 연관 필드: m.team, 묵시적 내부 조인, 탐색o

  • 컬렉션 값 연관 필드: m.orders, 묵시적 내부 조인, 탐색x

      **명시**
      select m from Member m join m.team t
      묵시
      select m.team from Member m
    
      컬렉션 값 연관 필드: 명시적 조인 통해 별칭
      select t.members.username from Team t(x)
      select m.username from Team t join t.members m(o)

JPQL - 페치 조인

  • 성능 최적화, 연관된 엔티티 함께 조회

      페치 조인
      select m from Member m join fetch m.team
    
      DISTINCT: 애플리케이션에서 엔티티 중복 제거
      컬렉션 페치 조인: 페이징x
      select distinct t
      from Team t join fetch t.members
      where t.name = ‘팀A’

JPQL - 다형성 쿼리

    select i from Item i where type(i) IN (Book, Movie)
    select i from Item i where treat(i as Book).auther = ‘kim’

JPQL - 엔티티 직접 사용

  • 엔티티 직접 사용 = 기본 키 값
      m = :member
      m.id = :memberId

JPQL - Named 쿼리

  • JPQL 쿼리에 이름 부여,
  • 애플리케이션 로딩 시점에 초기화
      @NamedQuery(
      name = "Member.findByUsername",
      query="select m from Member m where m.username = :username")

JPQL - 벌크 연산

  • 쿼리 한 번으로 여러 테이블 로우 변경 executeUpdate(), 영속성 컨텍스트 초기화

링크

https://www.inflearn.com/course/ORM-JPA-Basic