"인프런 - 자바 ORM 표준 JPA 프로그래밍 강의를 듣고 작성한 글 입니다."
www.inflearn.com/course/ORM-JPA-Basic#
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런
JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 프로그
www.inflearn.com
고아 객체란?
부모 Entity 와 연관관계가 끊어진 자식 Entity 를 자동으로 삭제하는 기능이다.
- orphanRemoval 라는 옵션을 사용한다.(orphanRemoval = true)
- Parent.java
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Child> childList = new ArrayList<>();
이전에 cascade 기능을 사용해 보면서 영속성 컨텍스트에 올라갔던 데이터들을 flush, clear 를 통해 DB 에 쿼리를 전달하여 데이터를 테이블에 저장한 후, 아래와 같은 코드를 작성하여 애플리케이션을 실행해보자.
- JpaMain.java
Parent findParent = em.find(Parent.class, parent.getId());
findParent.getChild().remove(0); // List 컬렉션에서 데이터를 삭제하면서 연관관계 단절
// 0 번째 인덱스, 즉 첫번째 데이터를 삭제한다.
그 결과 아래와 같은 hibernate SQL 을 출력하는 것을 볼 수 있다.
- hibernate SQL
Hibernate: // find 메소드로 인한 parent 객체 select
select
parent0_.id as id1_7_0_,
parent0_.name as name2_7_0_
from
Parent parent0_
where
parent0_.id=?
Hibernate: // getChildList 메소드로 인한 List select
select
childlist0_.parent_id as parent_i3_2_0_,
childlist0_.id as id1_2_0_,
childlist0_.id as id1_2_1_,
childlist0_.name as name2_2_1_,
childlist0_.parent_id as parent_i3_2_1_
from
Child childlist0_
where
childlist0_.parent_id=?
Hibernate: // select 한 컬렉션에서 첫번째 요소에 대한 remove 로 인해 연관관계가 단절되어 고아 객체가 된 child 데이터 삭제
/* delete hellojpa.Child */ delete
from
Child
where
id=?
주의할 점?
- CASCADE 와 마찬가지로 참조하는 곳이 하나일 때만 사용해야 한다.(특정 Entity 가 개인 소유일때만 사용 가능하다.)
- 마치 CascadeType.REMOVE 처럼 동작한다.
여기서 cascade 옵션을 지우고, 고아 객체 옵션만 남겨준 다음, persist 메소드를 다시 3번 호출해 주고 나서
em.remove(findParent); 처럼 찾아온 부모 객체 자체를 지워버리면 그 아래에 있는 List 에 삽입된 자식 객체의 데이터 까지 모두 지워지게 된다.
(물론 여기서 고아 객체 옵션 없이 그냥 cascade All 에서 위의 코드 em.remove(findParent); 를 사용해도 똑같이 자식 데이터들이 전부 삭제된다.)
- Parent.java
@OneToMany(mappedBy = "parent", orphanRemoval = true)
private List<Child> childList = new ArrayList<>();
- JpaMain.java
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);
- hibernate SQL
hibernate SQL
Hibernate: // em.remove(findParent); 로 인해 Parent 밑에 있는 Child 데이터 까지 모두 날아가는걸 볼 수 있다.
/* delete hellojpa.Child */ delete
from
Child
where
id=?
Hibernate:
/* delete hellojpa.Child */ delete
from
Child
where
id=?
Hibernate:
/* delete hellojpa.Parent */ delete
from
Parent
where
id=?
영속성 컨텍스트 + 고아 객체 생명주기
위의 둘을 섞어서 쓰는 것이 가능하다.(CascadeType.ALL + orphanRemoval = true 동시 사용)
- 스스로 생명 주기를 관리하는 Entity 는 em.persist() 로 영속화, em.remove() 로 제거한다.
- 라이프 사이클을 JPA 의 영속성 컨텍스트를 통해서 하는 것이다.(EntityManager 를 통해서)
- 그런데 구 옵션을 모두 활성화 하면 부모 Entity 를 통해서 자식의 생명 주기를 관리할 수 있다.
JPA 를 통해서 생명 주기를 관리하는 부모 Entity 와 달리, 자식 Entity 는 부모 Entity 를 통해서 자식의 생명 주기를 관리할 수 있다.
(DB 로 따지면 DAO 나 repository 가 없어도 된다는 뜻)
* 도메인 주도 설계(DDD) 의 Aggregate Root 개념을 구현할 때 유용하다.(지금은 이게 무슨 말인지 잘 모르겠다.)
'JPA' 카테고리의 다른 글
값 타입 - 기본 값 타입, 임베디드 타입(1) (0) | 2020.10.21 |
---|---|
실전예제 5 - 프록시 및 연관관계 (0) | 2020.10.17 |
영속성 전이(CASCADE) 와 고아 객체 - 1 (0) | 2020.10.17 |
프록시 객체와 지연 로딩, 즉시 로딩 - 2 (0) | 2020.10.16 |
프록시 객체와 지연 로딩, 즉시 로딩 - 1 (0) | 2020.10.16 |