스프링 잉

김성지·2022년 5월 14일
0

스프링기초

목록 보기
5/13

fetch =FetchType.LAZY
cascade =CascadeType.All

에 대해서 알아보자

object references an unsaved transient instance 에러가 떳다

어떻게 해결할건지 뭘 알아야하는지 적어보는 시간이 될 것이다!

왜 에러가 떳지?

FK 로 사용되는 컬럼값이 없는 상태에서 데이터를 넣으려다가 발생한 에러이다.!
내 상황에서는 member 가 없는 상태에서 book에 넣으려다가 발생햇음

해결은 cascade 옵션을 주어서 햇다.
@OneToMany 나 @ManyToOne 에 옵션으로 줄 수 있는 값이다.
Entity의 상태 변화를 전파시키는 옵션

즉 JPA 에서 Cascade 옵션을 사용하면 특정 엔티티를 영속 상태로 만들 때
연관된 엔티티도 함께 영속상태로 만들 수 있다.

N+1 이란?

member 조회할 때 Team도 함께 조회해야할까?

  • 비즈니스 로직에서 단순히 멤버관련 로직만 사용한다면 Team까지는 불러올 필요가 업음

JPA 에서는 지연로딩 LAZY를 사용해서 프록시로 조회하는 방법으로 해결

  • Member 와 Team 사이 다대일로 매핑될 때
  • @ManyToOne 어노테이션에 fetch 타입을 주면 됨

이때 어떤 로직에서 Member 조회하면 Team 객체의 클래스에는 Proxy 객체가 조회된다!

수정은 어떻게 하는거지?

여기서는 merge 를 사용할 거다.

public void save(Member member){

  if(Member.getId() == null){
     em.persist(member);
  } 
  
  else{ 
     em.merge(member);
  }
}

이런식으로 하면 대는데
merge 가 호출되면 우선 해당 엔티티를 1차 캐시에서 먼저 조회한다.

없다면 식별자(id)로 DB에서 엔티티를 검색해 가져와 준영속 상태의 엔티티 값을 대입 받게됨

준영속 상태의 member 자체를 영속성 컨텍스트에 넣는 것은 아니고

merge 는 준영속 객체를 영속하는 것이 아니라.
준영속 객체의 식별자와 일치하는 엔티티를 db에서 가져와 값을 대입받고,
해당 그 엔티티를 반환하는 것이ㅏㄷ.

주의
merge 는 엔티티 모든 필드를 그대로 변경하게됨
엔티티의 일부만 변경하게 되면 나머지는 데이터 잃고 null이 대입된다.

준영속 엔티티?

영속성 컨텍스트가 더는 관리하지 않는 엔티티이다.

  • 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)된 것
  • 영속성 컨텍스트가 제공하는 기능을 사용하지 못하게된다.

준영속 상태로 만드는 방법

  • em.detach(entity)
  • em.clear()
  • em.close()

merge는 준영속 상태의 엔티티를 영속상태로 변경할 때 사용하는 기능임.

정리하면

  1. 준영속 엔티티의 식별자 값으로 영속 엔티티를 조회한다.
    1-1. 찾은거는 영속 엔티티로 등록, 원래 엔티티는 그대로 준영속임
  2. 영속 엔티티의 값을 준영속 엔티티의 값으로 모두 교체한다.
  3. 트랜잭션 커밋 시점에 변경 감지 기능이 동작해서 데이터베이스에서 update sql이 실행된당.

0개의 댓글