Reference. 한 번에 끝내는 Java/Spring 웹 개발 마스터 초격차 패키지 Online
이전 글
더보기
1. 비영속 상태
- 영속성 컨텍스트가 해당 엔티티 객체를 관리하지 않는 상태
- java에서 new 객체를 의미
EntityManager
가 사용하는 상태 X
User
의 비영속 상태
@Service
public class UserService {
@Transactional
public void put(){
User user = new User();
user.setName("newUSer");
user.setEmail("newUser@test.com");
}
}
2. 영속 상태
- 엔티티가 영속성 컨텍스트 관리(manage)하에 있는 상태
- Spring Data JPA에서
userRepository.save(user)
와 같이EntityManager
를 사용하는 상태JpaRepository.save()
에는EntityManager.persist()
를 호출
@Service public class UserService { @Autowired private EntityManager entityManager; @Autowired private UserRepository userRepository; @Transactional public void put(){ User user = new User(); user.setName("newUSer"); user.setEmail("newUser@test.com"); //Spring Data JPA를 이용한 영속화 (save안에 EntityManaer persist호출 존재) userRepository.save(user); //EntityManaer를 이용한 영속화 entityManager.persist(user); } }
- 영속화 된 상태에서 객체를 수정(
setter
)하는 경우 수정 쿼리가 발생- 영속성 컨텍스트에
dirt Check (변경 감지)
기능- 엔티티를 컨텍스트에 로드를 할 때 정보를 스냅샷으로 복사
flush
,commit
,JPQL
실행시스냅샷-엔티티
값 비교 후 변경되면 수정쿼리 발생
- 대량의 엔티티를 다룰때 성능저하가 발생의 주의필요
@Transactional public void put(){ ... //EntityManaer를 이용한 영속화 entityManager.persist(user); user.setName("newUserAfterPersist"); } //실행 결과 Hibernate: insert into user (created_at, updated_at, email, gender, name) values (?, ?, ?, ?, ?) Hibernate: update user set updated_at=?, email=?, gender=?, name=? where id=?
- 영속성 컨텍스트에
3. 준영속 상태
- 영속화 된 객체를 분리해서 영속성 컨텍스트 밖으로 꺼내는 상태
- 준영속 상태로 변경하는 메소드
detach()
: 식별자를 전달함으로 하나의 건만 적용 (flush()
→ 준영속)detach()
를 사용하면 영속화 된 상태를flush()
후 준영속 상태로 변경
TestEntityManager.java (
entityManager.detach
구현체 )public <E> E persistFlushFind(E entity) { EntityManager entityManager = getEntityManager(); persistAndFlush(entity); Object id = getId(entity); entityManager.detach(entity); return (E) entityManager.find(entity.getClass(), id); }
clear()
,close()
: 영속성 컨텍스트로 반영하려는 값들을 모두 초기화 (flush()
없음)- 기존에 저장 된 영속 컨텍스트를 반영하려면
flush()
가 필요
@Transactional public void put(){ ... entityManager.merge(user); entityManager.flush(); //flush하지 않으면 모두 drop 됌 entityManager.clear(); }
- 기존에 저장 된 영속 컨텍스트를 반영하려면
- 일반적으로 영속화 된 객체를
detach()
사용X- Spring Data JPA에서는
detach()
가 존재X
@Transactional public void put(){ User user = new User(); user.setName("newUSer"); user.setEmail("newUser@test.com"); entityManager.persist(user); //영속상태 //영속 -> 준영속 (detach, clear, close) entityManager.detach(user); entityManager.clear(); entityManager.close(); user.setName("newUserAfterPersist"); //준영속상태 } //실행 결과 Hibernate: insert into user (created_at, updated_at, email, gender, name) values (?, ?, ?, ?, ?) //update 실행X
- Spring Data JPA에서는
merge()
를 이용하면 준영속 상태에 데이터 반영 가능persist
,merge
는JpaRepository
에서 제공하는save
명령어로 해결- 그래서 JpaRepository에선 반영하는 시점에 save를 사용
4. 삭제 상태
- 엔티티를 사용할 수 없는 상태로 변경
- 데이터베이스, 영속성 컨텍스트에서 모두 삭제 (
merge
오류 발생)
User user1 = userRepository.findById(1L).get();
entityManager.remove(user1);
user1.setName("marrrrrrrrrrrrrr");
entityManager.merge(user1);
//실행 결과
org.hibernate.ObjectDeletedException: deleted instance passed to merge: [com.example.bookmanager.domain.User#<null>]
java.lang.IllegalArgumentException: org.hibernate.ObjectDeletedException: deleted instance passed to merge: [com.example.bookmanager.domain.User#<null>]
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:797)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:780)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
'백엔드 > JPA' 카테고리의 다른 글
[ JPA ] 7. 영속성 전이 (Cascade) (0) | 2021.08.12 |
---|---|
[ JPA ] 6-4. 트랜잭션 매니저 (TransactionManager) (0) | 2021.08.08 |
[ JPA ] 6-2. Entity 캐시 (0) | 2021.08.07 |
[ JPA ] 6-1. 영속성 컨텍스트(Persistence Context) (0) | 2021.08.07 |
[ JPA ] 5-5. Entity Relations ( N:N @ManyToMany ) (0) | 2021.08.01 |