[Spring] Entity 생명 주기

WOOK JONG KIM·2022년 11월 21일
0

패캠_java&Spring

목록 보기
60/103
post-thumbnail

영속성 컨텍스트내에서 엔티티 매니저가 엔티티 상태를 어떻게 변화시키는지 알아볼 것

비영속상태(new), 영속 상태(managed), 준영속 상태(detached), 삭제 상태(removed)

new(비영속 상태)

@Transient 상태라고도 함

영속성 컨텍스트가 해당 엔티티 객체를 관리하지 않는 상태

이때는 엔티티 개념이 아니라 하나의 자바 오브젝트 개념

@Service
public class UserService {

    @Transactional
    public void put(){
        User user = new User();
        user.setName("newUser");
        user.setEmail("newUser@fastcampus.com");
    }
}

managed(영속 상태)

엔티티가 영속성 컨텍스트 관리(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=?

detached(준 영속 상태)

이미 영속화 된 객체를 분리해서 영속성 컨텍스트 밖으로 꺼내는 상태

준영속 상태로 변경하는 메소드

  1. detach() : 식별자를 전달하여 하나의 건만 적용 (flush() → 준영속)
    detach() 를 사용하면 영속화 된 상태를 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);
}
  1. clear(), close() : 영속성 컨텍스트로 반영하려는 값들을 모두 초기화 (flush() 없음)
    -> 기존에 저장 된 영속 컨텍스트를 반영하려면 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를 사용

Removed(삭제 상태)

엔티티를 사용할 수 없는 상태로 변경

데이터베이스, 영속성 컨텍스트에서 모두 삭제 (merge 오류 발생)

User user1 = userRepository.findById(1L).get();
entityManager.remove(user1);

user1.setName("marrrrrrrrrrrrrr");
entityManager.merge(user1);
profile
Journey for Backend Developer

0개의 댓글