DEV Community

HEEAH IM
HEEAH IM

Posted on

Entity State in JPA/ @Transactional

JPA 객체의 상태

1. Transient
객체를 생성하고, 값을 주어도 JPA나 hibernate가 그 객체에 관해 아무것도 모르는 상태. 즉, 데이터베이스와 매핑된 것이 아무것도 없다.
2. Persistent
저장을 하고나서, JPA가 아는 상태(관리하는 상태)가 된다. 그러나 .save()를 했다고 해서, 이 순간 바로 DB에 이 객체에 대한 데이터가 들어가는 것은 아니다. JPA가 persistent 상태로 관리하고 있다가, 후에 데이터를 저장한다.(1차 캐시, Dirty Checking(변경사항 감지), Write Behind(최대한 늦게, 필요한 시점에 DB에 적용) 등의 기능을 제공한다)
3. Detached
JPA가 더이상 관리하지 않는 상태. JPA가 제공해주는 기능들을 사용하고 싶다면, 다시 persistent 상태로 돌아가야한다.
4. Removed
JPA가 관리하는 상태이긴 하지만, 실제 commit이 일어날 때, 삭제가 일어난다.

@Transactional

토큰값이 DB 에 저장되지 않아서 확인해보니, 계정 저장 후, 이메일 토큰을 생성.
Detached 상태의 객체였던 것이다.

[AS-IS]

private Account saveNewAccount(@Valid SignUpForm signUpForm) {
    Account account = Account.builder()
            ....
            .build();
    return accountRepository.save(account);
}

public void processNewAccount(SignUpForm signUpForm) {
    Account newAccount = saveNewAccount(signUpForm);
    newAccount.generateEmailToken();
    sendSignupConfirmEmail(newAccount);
}
Enter fullscreen mode Exit fullscreen mode

[TO-BE]

private Account saveNewAccount(@Valid SignUpForm signUpForm) {
    Account account = Account.builder()
            ....
            .build();
    return accountRepository.save(account);
}

@Transactional
public void processNewAccount(SignUpForm signUpForm) {
    Account newAccount = saveNewAccount(signUpForm);
    newAccount.generateEmailToken();
    sendSignupConfirmEmail(newAccount);
}
Enter fullscreen mode Exit fullscreen mode

이 때 @Transactional 를 사용하여 processNewAccount의 객체도 transaction 범위내에 들도록 한다. 그럼 Detached 상태가 아닌 Persistent 상태가 유지가 된다. Persisent 객체의 경우, transaction이 종료될 때 DB에 sync 된다. 따라서, 생성된 토큰 값도 저장된다.

*참고자료
백기선 인프런 강의

Top comments (0)