JPA에서 Entity와 LazyLoading 복습

Entity

  • @Entity: JPA에서 데이터베이스 테이블과 매핑되는 클래스임을 나타내는 어노테이션
  • 해당 클래스는 DB 테이블로 인식되며, 이를 기반으로 JPA가 SQL 쿼리를 자동 생성하고 실행한다

    Getter & Setter

    Getter

    • 클래스의 private 필드 값을 외부에서 읽을 수 있게 하는 메서드 Setter
    • 클래스의 private 필드 값을 외부에서 변경할 수 있게 하는 메서드

    Lombok을 사용하면 @Getter와 @Setter로 모든필드에대해 get/set 메서드를 자동으로 생성한다

    
    @Getter
    @Builder  // 빌더 패턴으로 객체 생성 가능
    @AllArgsConstructor // 모든 필드를 인자로 받는 생성자 생성
    @NoArgsConstructor(access= AccessLevel.PROTECTED) // 파라미터가 없는 기본 생성자를 생성, 생성자의 접근제어자를 protected로 설정
    @Entity
    @Table(name = "user")
    public class User {
      @Entity // 이 클래스가 JPA 엔티티임을 선언
      @Table(name = "user") // 매핑될 테이블 이름을 "user"로 명시
      @Id // 해당 필드가 기본 키임을 명시
      @GeneratedValue(strategy = GenerationType.IDENTITY) // 기본 키 값이 DB에서 자동으로 증가(AUTO_INCREMENT) 되도록 설정
      private Long t_id;
    
      @Column(nullable = false) //  해당 필드를 DB의 열(컬럼)으로 매핑, NOT NULL 제약 조건 추가
      private String username;
    
      @OneToOne // UserCredentials 엔티티의 user 필드가 연관관계의 주인
        (mappedBy = "user", // UserCredentials 테이블과 1:1 관계
        cascade = CascadeType.ALL,  // UserCredentials 엔티티의 user 필드가 연관관계의 주인
        fetch = FetchType.LAZY)   // 지연 로딩으로 userCredentials가 실제로 접근될 때 DB 조회 수행
      private UserCredentials userCredentials;
    
       public void setCredentials(UserCredentials credentials) {  // UserCredentials 엔티티를 수동으로 설정할 수 있도록 setter 제공
          this.userCredentials = credentials;
      }
    }
    
  • Entity 관련 어노테이션 정리

    구성 요소 설명
    @Entity 해당 클래스는 JPA가 관리하는 DB 테이블 매핑 객체
    @Id 기본 키 식별자
    @GeneratedValue 기본 키 자동 생성 전략 지정
    @Column 필드를 DB 컬럼과 매핑
    @OneToOne 연관 엔티티와 1:1 관계 설정
    @Builder 등 Lombok 객체 생성 간 편의 제공


LazyLoading

  • 지연로딩은 연관된 데이터를 즉시 불러오지않고, 필요한 시점에 가져오는 방식이다

  • 아래의 코드에서 User 엔티티를 조회할 때, UserCredentials의 정보는 바로 로딩되지않는다
  • getCredentials()를 호출하는 시점에 쿼리가 실행되고 데이터를 가져온다

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private UserCredentials credentials;
    

사용 이유

  • OneToOne 또는 OneToMany에서 fetch 옵션을 설정하지 않으면 기본적으로 Eager Loading이 적용된다
  • 유저와 연관된 데이터가 많은 경우 LazyLoading 설정이 없다면 불필요한 정보들까지 가져오게 된다
  • 이경우 많은 JOIN 쿼리가 발생하여 DB에 오버헤드가 발생하여, 애플리케이션에 과부하가 올 수 있다

사용시 장점

  1. 연관된 데이터가 필요한 경우 쿼리를 실행하여 불필요한 쿼리를 최소화
  2. 사용하지않는 객체까지 메모리에 로딩하지 않아 메모리 절약
  3. 데이터의 용량이 큰 경우에도 빠른 응답이 가능

⚠️ 주의할 점

트랜잭션 종료 후 Lazy 필드 접근 시 LazyInitializationException이 발생

해결방법

  • 트랜잭션 내에서 접근
  • @Transactional 을 사용
  • Fetch Join 을 활용한 명시적 조회


JPA Fetch 전략 기본값

  • EAGER : 연관된 엔티티를 즉시 조회
  • LAZY : 연관된 컬렉션은 필요할 때만 조회

    관계 종류 기본 Fetch 전략
    @OneToOne EAGER (즉시 로딩)
    @ManyToOne EAGER (즉시 로딩)
    @OneToMany LAZY (지연 로딩)
    @ManyToMany LAZY (지연 로딩)

댓글남기기