본문 바로가기
spring/JPA

[JPA] 프록시와 연관관계 관리

by H.초보개발자 2023. 12. 11.
반응형

이 글은 인프런의 김영한 강사님 자바 ORM 표준 JPA 프로그래밍-기본 편 강의 내용을 바탕으로 작성되었습니다.

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

저는 야생형이 아니라 학자형인가봐요^^ 활용편 넘어갔다 30% 정도 듣고 도저히 답답해서 기본편을 들어버렸네요^^. 한주 한주 김영한님 강의 들으니 렙업되는 모습을 스스로 느낍니다. 특히 실

www.inflearn.com

프록시란?

프록시 객체란 실제 객체가 아닌, 실제 클래스를 상속받아서 겉모양이 같게 만들어진 객체 (임시 객체라고 생각하면 편함) 하지만 프록시 객체를 호출하면 실제 객체의 메소드에서 호출이 됨

 

프록시 객체는 실제 객체에서 호출이 되었을때 초기화가 됨

 

LAZY를 사용해서 프록시로 조회가 가능하다

@Entity
public class Member {
  @Id
  @GeneratedValue
  private Long id;
  @Column(name = "USERNAME")
  private String name;
  @ManyToOne(fetch = FetchType.LAZY) //** @JoinColumn(name = "TEAM_ID")
  private Team team;

}

예를들어

Member member = em.find(Member.class, 1L); 

이 명령어로 사용자를 조회를 하면 일단 프록시로 Team에 대한 엔티티 정의(?)만 들고 있음, 그 이후에

Team team = member.getTeam();

이 명령어로 실제 DB에서 데이터를 조회하고 프록시는 초기화 됨

 

하지만 Member와 Team이 항상 같이 조회가 된다면

@Entity
public class Member {
  @Id
  @GeneratedValue
  private Long id;
  @Column(name = "USERNAME")
  private String name;
  @ManyToOne(fetch = FetchType.EAGER) //** @JoinColumn(name = "TEAM_ID")
  private Team team;

}

이런식으로 @ManyToOne(fetch = FetchType.EAGER) 설정해주면됨. 이렇게 되면 SQL에서 한번에 함께 조회가 됨

 

주의 사항

  • 가급적 실무에서는 EAGER 사용 금지
  • @ManyToOne, @OneToOne은 기본이 EAGER이기 때문에 LAZY로 변경해줘야 됨

 

CASCADE란?

부모 엔티티를 저장할때 자식 엔티티도 함께 저장됨

@OneToMany(mappedBy="parent", cascade=CascadeType.ALL) -> 이런식으로 하면 자식 엔티티도 모두 함께 저장됨

 

고아 객체

고아 객체 제거: 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제됨

@Entity
public class Parent {
    @Id
    @GeneratedValue
    private Long id;
    private String name;

    @OneToMany(mappedBy = "parent",cascade = CascadeType.REMOVE,orphanRemoval = true)
    private List<Child> childList = new ArrayList<>();
    public void addChild(Child child){
        childList.add(child);
        child.setParent(this);
    }
}

이런식으로 엔티티를 만든 후에 

            Parent findParent = em.find(Parent.class, parent.getId());
            findParent.getChildList().remove(0);
            tx.commit();

이런식으로 리스트에서 지워 준다면 지워진 자식테이블에서 해당 데이터가 삭제가 됨

 

예제

  • 모든 연관관계를 지연 로딩으로 설정
  • @ManyToOne, @OneToOne은 기본이 즉시 로딩이므로 지연 로딩으로 변경

연관관계 지연로딩 변경

@Entity
public class Category extends BaseEntity{

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PARENT_ID")
    private Category parent;

    @OneToMany(mappedBy = "parent")
    private List<Category> child = new ArrayList<>();

    @ManyToMany
    @JoinTable(name = "CATEGORY_ITEM",
                joinColumns = @JoinColumn(name = "GATEGORY_ID"),
                inverseJoinColumns = @JoinColumn(name = "ITEM_ID"))
    private List<Item> items = new ArrayList<>();
}
  • Order -> Delivery를 영속성 전이 ALL 설정
  • Order -> OrderItem을 영속성 전이 ALL 설정
@Entity
@Table(name = "ORDERS")
public class Order extends BaseEntity{
    @Id
    @GeneratedValue
    @Column(name = "ORDER_ID")
    private Long id;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="MEMBER_ID")
    private Member member;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "DELIVERY_ID")
    private Delivery delivery;
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();
    private LocalDateTime orderDate;
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
}

 

반응형

'spring > JPA' 카테고리의 다른 글

[JPA] 객체지향 쿼리 언어(JPQL)  (0) 2023.12.14
[JPA] 값타입  (0) 2023.12.12
[JPA] 고급매핑  (0) 2023.12.11
[JPA] 다양한 연관관계 매핑  (0) 2023.12.08
[JPA] 연관관계 매핑 기초  (2) 2023.12.07