JPA 엔티티의 생명주기는 비영속, 영속, 준영속, 삭제의 네 가지 상태로 구분됩니다.
- 비영속(Transient): 객체를 생성했지만 아직 영속성 컨텍스트가 관리하지 않는 상태입니다.
- 영속(Managed):
persist()로 저장하거나 조회하여 영속성 컨텍스트가 관리하는 상태입니다. 변경 감지와 1차 캐시의 대상이 됩니다. - 준영속(Detached): 한때 영속 상태였지만
detach(),clear(),close()등으로 영속성 컨텍스트의 관리를 벗어난 상태입니다. 값을 변경해도 변경 감지가 동작하지 않습니다. - 삭제(Removed):
remove()가 호출되어 삭제 대상으로 관리되는 상태입니다. 실제 DELETE SQL은 보통 플러시 시점에 실행됩니다.
merge()를 사용하면 준영속 엔티티의 값을 영속 상태의 엔티티에 복사할 수 있습니다. 이때 인자로 전달한 객체 자체가 다시 영속 상태가 되는 것이 아니라, 별도의 영속 엔티티가 반환된다는 점에 주의해야 합니다.
persist()를 호출하면 INSERT SQL이 즉시 실행되나요?일반적으로 엔티티는 먼저 영속 상태가 되고 INSERT SQL은 플러시 시점까지 지연될 수 있습니다. 다만 IDENTITY 식별자 전략처럼 식별자를 얻기 위해 데이터베이스 INSERT가 필요한 경우에는
persist()시점에 SQL이 실행될 수 있습니다.
준영속 상태에서는 어떤 기능을 사용할 수 없나요?
1차 캐시, 변경 감지, 지연 로딩처럼 영속성 컨텍스트의 관리가 필요한 기능을 사용할 수 없습니다. 초기화되지 않은 지연 로딩 연관관계에 접근하면
LazyInitializationException이 발생할 수 있습니다.
merge()사용 시 주의할 점은 무엇인가요?전달한 준영속 객체가 아니라
merge()가 반환한 객체가 영속 상태입니다. 또한 전달받지 않은 필드까지null로 덮어쓸 수 있으므로, 변경할 엔티티를 조회한 뒤 필요한 값만 수정하는 방식이 더 안전합니다.