ORM, 영속 상태로 만드는 순서
Velog에서도 포스팅 중입니다:)
영속 상태로 만드는 순서
의문점...Parent 객체가 Child 객체 c1,c2를 child로 가지는 연관관계가 있다면, em.persist()는 3번 호출해야 할 것이다. 그 순서를 바뀌어도 괜찮을까??case 1)
velog.io
의문점...
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)
resultem.persist(parent); em.persist(c1); em.persist(c2);
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를 가지는 엔티티)의 반대편 엔티티를 먼저 영속 상태로 만들고 연관 관계 주인을 영속 상태로 만들어야 성능 이슈가 생기지 않는다.