2020-4-15 스프링 Data common (4) JPA Cascade
Cascade
- cascade : 엔티티의 상태 변화를 전파시키는것이다. 연관이 되어있는 엔티티에도 상태변화를 똑같이 전이 시키고 싶다.
엔티티의 상태
- Transient : JPA가 모르는 상태
- Persistent : JPA가 관리중인 상태(1차 캐시, Dirty Checking, Write Behind…)
- Detached : JPA가 더이상 관리하지 않은 상태
- Removed: JPA가 관리하긴 하지만 삭제하기로 한 상태
public void run(ApplicationArguments args) throws Exception {
Account account = new Account();
account.setUsername("jimmy");
account.setPassword("hibernate");
Study study = new Study();
study.setName("spring data study");
account.addStudy(study);
Session session = entityManager.unwrap(Session.class);
session.save(account);
session.save(study);
System.out.println("=======================");
Account noSelect = session.load(Account.class, account.getId());
noSelect.setUsername("whiteship");
noSelect.setUsername("whiteship1");
noSelect.setUsername("whiteship2");
noSelect.setUsername("whiteship3");
noSelect.setUsername("update");
System.out.println("no select " + noSelect.getUsername());
}
- 위의 코드들은 Transient상태.
- save를 하게 되면 persistent상태가 된다. 이때 바로 DB에 데이터가 들어가는것은 아니다. JPA가 상태를 보고 추후 DB에 저장한다.
- persistent에서는 1차캐시의 역할을 하기때문에, 밑에서 select를 날리지도 않고 바로 가져온다.
- Dirtycheck: 객체의 변경사항을 비교한다.
- write behind : 트랜잭션이 끝나면 객체의 변경사항을 쿼리로 날리게 된다.
- 위의 코드에서 setUsername이 엄청나게 많은데, 결과론적으로는 update쿼리가 1번만 나간다. 이 역시도 setUseranme이 초창기 값인 jimmy라면 update쿼리가 날라가지 않는다. 이게 캐싱기능이 있기때문에 가능하다.
- 트랜잭션이 끝나고 세션밖으로 나오면 Detached상태가 된다.
- detached상태에서는 dirty checking, write behind, lazy-loading등이 발생하지도 않는다. 다시 persistent로 만들기 위해 repersitent를 해야한다.
- cascade의 경우 oneToMany, ManyToOne의 관계가 아닌 Parent, Child관계에서 적용할 수 있다.
- session.load() : 프록시로도 가져올 수 있다.
- session.get() : 무조건 DB에서 가져오고 해당하는게 없으면 null로 만든다.
Written on April 15, 2020