Member라는 엔티티가 있다고 하자 나는 Member의 이름정도만 알면되는데 이를 조회할때 Member와 연결되어있는 Team 엔티티가 있다면 얘까지 전부 조인으로 가져와야할까?
그럼 언제 Team을 가져와야할까?
이때 이를 효율적으로 만들어주는것이 프록시 이다.
이러한 내부는 텅비어있지만 어떤것들이 들어있어야하는지는 알수있는 객체가 프록시이다.
프록시객체는 정말 데이터가 필요할때 getName()
같은 매서드가 작동할때 초기화 요청을통해 그때 DB에서 데이터를 가져와서
프록시 객체가 사라지는게 아닌 진짜 객체에 접근하는 방식으로 데이터를 가져온다.
@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와 Team이 지연로딩으로 연결되어있다면 처음 Member를 가져올때 Member의 데이터는 직접 바로 가져와도 Team에 해당하는 객체는 프록시로 들고있게된다.
이후에 member.getTeam()
같은 것이 호출된다면 그때 Team을 초기화하여 데이터를 가져오는것이 지연로딩이다.
이에 반대로는 즉시로딩이 있는데 이는 실무에서 추천하지않는다 전부 지연로딩으로 사용을 권장한다.
JPQL을 사용할때는 내가 적은 SQL이 직접 날라가게되는데 이에 즉시로딩이라고 join질의가 포함되게 만들어주지않는다. 그렇다면 즉시로딩이 되어있는 쿼리를 다시 날리게되면서 쿼리가 엄청나게 나가게되는일이 많다.
Child child1 = new Child();
Child child2 = new Child();
Parent parent = new Parent();
parent.addChild(child1);
parent.addChild(child2);
em.persist(parent);
em.persist(child1);
em.persist(child2);
영속성 전이를 사용하지 않으면 Parent
에 의해 관리되는 Child
까지 전부다 persist
해서 영속성 관리를 해줘야한다.
또한 parent
가 삭제되었다고 했을때 달려있던 child
들은 아무연결도없이 붕떠있게 된다.
이를
CascadeType.ALL + orphanRemovel=true
사용해서 관리할 수 있다. 두개를 한꺼번에 적용해주면 자식이 생성되어 부모로 들어갈때 영속성 컨텍스트에 자동으로 넣어주고 부모가 사라졌을때 자식도 자동으로 삭제시켜준다.