엔티티 등록
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jakarta.persistence");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
//엔티티 매니저는 데이터 변경 시 트랜잭션을 시작해야한다.
tx.begin();
em.persist(memberA);
em.persist(memberB);
//여기까진 insert sql을 데이터베이스에 보내지 않는다.
//commit하는 순간 insert sql을 보낸다.
tx.commit();
|
cs |
엔티티 매니저는 트랜잭션을 커밋하기 직전까지 DB에 저장하지 않고 내부 저장소에 모아둔다.
그리고 커밋할 때 모아둔 쿼리를 DB에 보내는데 이것을 트랜잭션을 지원하는 쓰기 지연이라 한다.
persist()를 통해 memberA, memberB를 영속화하고
1차 캐시에 엔티티를 저장하면서 동시에 회원 엔티티 정보로 등록 쿼리를 만든다.
이것을 쓰기 지연 SQL 저장소에 보관한다.
그 후 마지막 commit후 엔티티 매니저는 영속성 컨텍스트를 플러시 하여 변경 내용을 데이터베이스에 동기화하고 등록, 수정, 삭제한 엔티티를 반영한다.
좀 더 구체적으로는 쓰기 지연 SQL 저장소에 모인 쿼리를 데이터베이스에 보내는 것이다.
엔티티 수정
- SQL 수정 쿼리의 문제점
SQL을 사용하면 수정 쿼리를 직접 작성해야 한다.
하지만 프로젝트가 커지고 요구사항이 늘어나면 그에 맞게 쿼리도 점점 변경된다.
이런 개발 방식의 문제점은 수정 쿼리가 많아지는 것은 물론이고 비즈니스 로직을 분석하기 위해서 SQL을 계속 확인해야 한다.
결국 직접적이든 간접적이든 비즈니스 로직이 SQL에 의존하게 된다.
- 변경감지
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jakarta.persistence");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Member memberA = em.find(Member.class, "memberA");
memberA.setUsername("hi");
memberA.setAge(20);
//em.update(memberA); tx.commit();
|
cs |
JPA로 수정할 때는 단순히 조회해서 데이터만 변경하면 된다.
주석처리된 em.update 이런 메소드는 없다.
이렇게 엔티티의 변경사항을 데이터베이스에 자동으로 반영하는 기능을 변경 감지라 한다.
JPA는 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장해 두는데 이것을 스냅샷이라 한다.
그리고 플러시 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾는다.
변경 감지로 인해 실행된 UPDATE 문은 자세히 보면 수정된 컬럼만 업데이트하는 게 아니라 전체 필드를 업데이트한다.
그렇기에 필드가 많거나 저장되는 내용이 크면 수정된 데이터만 사용해서 동적으로 UPDATE SQL을 생성하는 전략을 선택하면 되고 이때, 하이버네이트 확장 기능을 사용해야 한다.
( @org. hibernate.annotations.DynamicUpdate )
* 주의
변경 감지는 영속성 컨텍스트가 관리하는 영속상태의 엔티티에만 적용된다.
비영속, 준영속 상태의 엔티티는 값을 변경해도 데이터베이스에 반영되지 않는다.
엔티티 삭제
엔티티를 삭제하려면 먼저 삭제 대상 엔티티를 조회해야 한다.
Member member = em.find(Member.class, "memberA");
em.remove(member);
|
cs |
em.remove()에 삭제 대상 엔티티를 넘겨주면 삭제한다.
물론 바로 삭제가 아니라 등록과 비슷하게 쓰기 지연 SQL 저장소에 등록하고 이후 트랜잭션 커밋을 해서 플러시를 호출하면 실제 삭제 쿼리가 데이터베이스로 전달된다.
참고로 em.remove(member)를 호출하는 순간 member는 영속성 컨텍스트에서 제거된다.
'스프링' 카테고리의 다른 글
[JPA] 영속성 관리[5] (0) | 2024.12.10 |
---|---|
[JPA] 영속성 관리[4] (1) | 2024.12.09 |
[JPA] 영속성 관리[2] (0) | 2024.11.26 |
[JPA] 영속성 관리[1] (0) | 2024.11.25 |
[Spring Boot] 동적 쿼리 처리를 위해 Querydsl 알아보기 (0) | 2023.02.13 |