영속 상태로 만드는 순서

60jong·2022년 10월 25일
0

JPA

목록 보기
3/5

의문점...
Parent 객체가 Child 객체 c1,c2를 child로 가지는 연관관계가 있다면, em.persist()는 3번 호출해야 할 것이다. 그 순서를 바뀌어도 괜찮을까??


Parent parent = new Parent();

Child child1 = new Child();
Child child2 = new Child();

parent.addChild(child1);
parent.addChild(child2);

  • case 1)
em.persist(c1);
em.persist(c2);
em.persist(parent);

result

Hibernate: 
    /* insert hellojpa.domain.Child
        */ insert 
        into
            Child
            (name, parent_id, id) 
        values
            (?, ?, ?)
Hibernate: 
    /* insert hellojpa.domain.Child
        */ insert 
        into
            Child
            (name, parent_id, id) 
        values
            (?, ?, ?)
Hibernate: 
    /* insert hellojpa.domain.Parent
        */ insert 
        into
            Parent
            (name, id) 
        values
            (?, ?)
Hibernate: 
    /* update
        hellojpa.domain.Child */ update
            Child 
        set
            name=?,
            parent_id=? 
        where
            id=?
Hibernate: 
    /* update
        hellojpa.domain.Child */ update
            Child 
        set
            name=?,
            parent_id=? 
        where
            id=?
  • case 2)
em.persist(parent);
em.persist(c1);
em.persist(c2);

result

Hibernate: 
    /* insert hellojpa.domain.Parent
        */ insert 
        into
            Parent
            (name, id) 
        values
            (?, ?)
Hibernate: 
    /* insert hellojpa.domain.Child
        */ insert 
        into
            Child
            (name, parent_id, id) 
        values
            (?, ?, ?)
Hibernate: 
    /* insert hellojpa.domain.Child
        */ insert 
        into
            Child
            (name, parent_id, id) 
        values
            (?, ?, ?)

문제 상황

case 2에서는 3개의 insert 쿼리가 나갔지만, case 1에서는 추가로 2개의 update 쿼리가 나갔다.

결론

객체를 영속 상태로 만들면 (=영속성 컨텍스트에 저장) 쓰기 지연 SQL 저장소에 쿼리가 저장된다.

case 1의 경우 child1과 child2가 먼저 영속 상태로 되면서 쓰기 지연 SQL 저장소에는
insert into Child values(1,'child1',null), insert into Child values(2,'child2',null)가 저장됐을 것이다.

child의 parent_id가 null??

parent.addChild(Child child) {
	parent.getChildren.add(child);
    child.setParent(this);
}

이어서 child에는 parent가 설정된 것이 아닌가??

But

parent는 객체이고 DB에는 parent_id로 존재한다. 그러나 child1의 insert시기에는 DB에 저장된 parent가 없다. (쓰기 지연 SQL 저장소는 Queue 구조임을 확인할 수 있다.)

따라서 child1 insert시에는 parent_id가 null이게 되는 것이고, parent의 insert시에는 parent.addChild()에 있던 child.setParent()에 의해 Dirty Checking이 발생해 해당 child들에 대한 update 구문이 쓰기 지연 SQL 저장소에 저장되는 것이다.

그리고 parent_id는 3이 된다. -- 이 부분은 좀 더 공부해서 궁금증을 해결해야 겠다.


따라서

연관 관계가 있는 엔티티들을 영속 상태로 만들 때에는 연관 관계 주인(주로 fk를 가지는 엔티티)의 반대편 엔티티를 먼저 영속 상태로 만들고 연관 관계 주인을 영속 상태로 만들어야 성능 이슈가 생기지 않는다.

profile
울릉도에 별장 짓고 싶다

0개의 댓글