영속성 컨텍스트내에서 엔티티 매니저가 엔티티 상태를 어떻게 변화시키는지 알아볼 것
비영속상태(new)
, 영속 상태(managed)
, 준영속 상태(detached)
, 삭제 상태(removed)
@Transient
상태라고도 함
영속성 컨텍스트가 해당 엔티티 객체를 관리하지 않는 상태
이때는 엔티티 개념이 아니라 하나의 자바 오브젝트 개념
@Service
public class UserService {
@Transactional
public void put(){
User user = new User();
user.setName("newUser");
user.setEmail("newUser@fastcampus.com");
}
}
엔티티가 영속성 컨텍스트 관리(manage)하에 있는 상태
-> 객체의 변화를 별도로 처리하지 않더라도 DB에 반영됨
@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(DB 반영 작업) 실행시 스냅샷-엔티티 값 비교 후 변경되면 수정쿼리 발생
-> 대량의 엔티티를 다룰때 성능저하가 발생의 주의필요
@Transactional
public void put(){
...
//EntityManaer를 이용한 영속화
entityManager.persist(user);
// 별도의 save를 하지 않아도 이름이 변경 되는 것(update 쿼리 실행 )을 볼 수 있음
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=?
이미 영속화 된 객체를 분리해서 영속성 컨텍스트 밖으로 꺼내는 상태
준영속 상태로 변경하는 메소드
flush() → 준영속
)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);
}
flush() 없음
)@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
merge() 를 이용하면 준영속 상태에 데이터 반영 가능
persist, merge는 JpaRepository에서 제공하는 save 명령어
로 해결
그래서 JpaRepository에선 반영하는 시점에 save를 사용
엔티티를 사용할 수 없는 상태로 변경
데이터베이스, 영속성 컨텍스트에서 모두 삭제 (merge 오류 발생)
User user1 = userRepository.findById(1L).get();
entityManager.remove(user1);
user1.setName("marrrrrrrrrrrrrr");
entityManager.merge(user1);