Jpa-프록시, 값 타입, 객체지향 쿼리 언어

1 분 소요

fetch, cascade

  • 프록시란? (→ 결국 지연로딩을 위함)
    • 엔티티를 조회할 때 연관관계가 있는 엔티티를 항상 사용하는건 아니다.
    • Member에 있는 name(String)이나 id(Long)은 바로 쓰이는데 team(Team)이란 필드는 조회안하면 Member를 조회할 때 Team을 조회할 필요가 없다. 그래서 Member를 조회할 때 가짜객체인 프록시객체를 만들어 잠깐 실제 Team객체 불러오는걸 지연 해놓고 진짜 team필드가 쓰일 때(team.getName()) 프록시를 통해 실제 객체를 불러와서 쓴다. 이게 프록시의 대충 이해한 개념이다.
  • 프록시 초기화란?
    • 영속성 컨텍스트에 요청이 들어온 실제 엔티티가 없을 때 실제 엔티티 생성을 요청하는 것.
    • 누가? 프록시 객체가.
  • 프록시가 초기화되지 않는 경우
    • 이미 영속성컨텍스트에 해당 엔티티가 올라와져있을 때 → 걍 실제 객체를 가져온다.
    • 식별자(Id)를 조회할 때는 받았던 파라미터를 그대로 출력한다.
    • 영속상태가 아닐 경우엔 프록시초기화가 안된다.
    • 지연로딩에서 쓰이는게 프록시
  • 지연로딩(FetchType.LAZY) vs 즉시로딩(FetchType.EAGER)
    • 상황에 따라 선택이 바뀐다. 회원과 팀 엔티티가 대부분의 어플리케이션 로직에서 같이 쓰인다면 둘은 그냥 즉시로딩으로 설정해놓는 것이 편하다.
    • 하지만 가끔씩 조회하기위해 참조를 쓰는 곳이면 지연로딩을 하는것이 효율적이다.
    • 보통 @OneToMany의 필드인 컬렉션을 로딩하는건 지연로딩하는걸 권장한다.
    • 추천방법 : 처음엔 전부 지연로딩으로 했다가 개발이 완료단계에 왔을 때 실제 사용하는 상황을 보고 필요한 곳에만 즉시로딩을 사용해서 최적화시키면 된다.
  • 선택적 관계면 외부조인 (optional=true), 필수적 관계면 내부조인 (optional=false)

  • 영속성 전이
    • 엔티티를 영속화할 때 연관된 엔티티도 같이 영속화 하거나 영속관계를 끊을 때 자동으로 연관관계의 엔티티의 영속성을 끊어버리는 편리함을 제공
    • cascade = CascadeType.PERSIST
    • cascade = CascadeType.REMOVE
    private static oid saveWithCascade(EntityManger em) {
      Child child1 = new Child();
      Child child2 = new Child();
    
      Parent parent = new Parent();
      child1.setParent(parent);
      child2.setParent(parent);
      parent.getChildren().add(child1);
      parent.getChildren().add(child2);
    
      em.persist(parent); 
    }
  • 마지막 줄에 em.persist(parent); 이거 하나만으로 child1과 child2을 전부 영속화시켰다!

값 타입

  • 이게 값타입을 이용한 엔티티
      @Entity
      public class Member {
        @Id
        private Long id;
        private String name;
        
        @Embedded
        private Period workPeriod;
        
        @Embedded
        private Address homeAddress;
      }
        
      @Embeddable
      public class Period{
        
        @Temporal(TemporalType.DATE)
        private Date startDate;
          
        @Temporal(TemporalType.DATE)
        private Date endDate;
      }
        
      @Embeddable
      public class Address{
        private String city;
        private String street;
        private String zipcode;
      }
    
  • 이러면 MEMBER테이블엔 7개의 컬럼이 들어온다.
  • 추가적으로 값타입 클래스(Address)에는 equals와 hashCode 메소드가 오버라이딩 되어야한다

객체지향 쿼리 언어

  • JPQL
  • Criteria
  • QueryDSL
  • 네이티브 SQL

  • JPQL은 필수적으로 알아야하는거고 Criteria나 QueryDSL은 결국 JPQL을 실수없이 효과적으로 쓰기위해 존재하는 도구와 같은 것
  • 결국 JPQL을 완벽히 손에 익을만큼 연습하고 QueryDSL로 넘어가는게 좋아보임.

  • JPQL
    public interface MemberRepository extends JpaRepository<Member, Long> {
      // 쿼리 메소드
      List<Member> findByName(String name);
    
      @Query("SELECT m FROM Member m JOIN m.team t WHERE t.name=:teamName")
      List<Member> findMember(@Param(teamName) String teamName);
    }
    
    public interface BoardRepository extends JpaRepository<BoardEntity, Integer>{
    
    @Query("SELECT file FROM BoardFileEntity file WHERE board_idx = :boardIdx AND idx = :idx")
    BoardFileEntity findBoardFile(@Param("boardIdx") int boardIdx, @Param("idx") int idx);
    }
    

카테고리:

업데이트:

댓글남기기