[SpringBoot] 영속성 컨텍스트 실습

LaStella·2023년 4월 11일
@Slf4j
@SpringBootTest
public class PersistenceContextTest {

    @Autowired
    CustomerRepository repository;

    @Autowired
    EntityManagerFactory emf;

    @BeforeEach
    void setUp() {
        // 테스트 메소드를 시작하기 전 저장되어있는 데이터를 지워줍니다.
        repository.deleteAll();
    }

    @Test
    @Order(1)
    @DisplayName("고객 저장 테스트")
    void testSaveCustomer() {
        EntityManager entityManager = emf.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        transaction.begin(); // table의 row가 변경이 되는 작업은 transaction begin, commit 내에서 이루어져야합니다.

        Customer customer = new Customer(); // 비영속상태
        customer.setId(1L);
        customer.setFirstName("aaa");
        customer.setLastName("bbb");

        entityManager.persist(customer); // 비영속 -> 영속 (영속화)
        transaction.commit(); // entityManager.flush(); 가 실행됩니다.(쓰기 지연 저장소에 있는 쿼리가 실행됩니다.)
    }

    @Test
    @Order(2)
    @DisplayName("고객 조회 테스트(DB)")
    void testFindCustomerInDB() {
        EntityManager entityManager = emf.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        transaction.begin();

        Customer customer = new Customer(); // 비영속상태
        customer.setId(1L);
        customer.setFirstName("aaa");
        customer.setLastName("bbb");

        entityManager.persist(customer); // 비영속 -> 영속 (영속화)
        transaction.commit(); // entityManager.flush();

        entityManager.detach(customer); // 영속 -> 준영속, 1차 캐시에 정보가 삭제됩니다.

        Customer selectedCustomer = entityManager.find(Customer.class, 1L);
        log.info("{} {}", selectedCustomer.getFirstName(), selectedCustomer.getLastName());
    }

    @Test
    @Order(3)
    @DisplayName("고객 조회 테스트(1차 캐시)")
    void testFindCustomerInCache() {
        EntityManager entityManager = emf.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        transaction.begin();

        Customer customer = new Customer(); // 비영속상태
        customer.setId(1L);
        customer.setFirstName("aaa");
        customer.setLastName("bbb");

        entityManager.persist(customer); // 비영속 -> 영속 (영속화)
        transaction.commit(); // entityManager.flush();

        Customer selected = entityManager.find(Customer.class, 1L);
        log.info("{} {}", selected.getFirstName(), selected.getLastName());
    }

    @Test
    @Order(4)
    @DisplayName("고객 수정 테스트")
    void testUpdateCustomer() {
        EntityManager entityManager = emf.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        transaction.begin();

        Customer customer = new Customer(); // 비영속상태
        customer.setId(1L);
        customer.setFirstName("aaa");
        customer.setLastName("bbb");

        entityManager.persist(customer); // 비영속 -> 영속 (영속화)
        transaction.commit(); // entityManager.flush();

        transaction.begin();
        customer.setFirstName("ccc");
        customer.setLastName("ddd");

        transaction.commit();
    }

    @Test
    @Order(5)
    @DisplayName("고객 삭제 테스트")
    void testRemoveCustomer() {
        EntityManager entityManager = emf.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        transaction.begin();

        Customer customer = new Customer(); // 비영속상태
        customer.setId(1L);
        customer.setFirstName("aaa");
        customer.setLastName("bbb");

        entityManager.persist(customer); // 비영속 -> 영속 (영속화)
        transaction.commit(); // entityManager.flush();

        transaction.begin();

        entityManager.remove(customer);

        transaction.commit();
    }

}

고객 조회 테스트 (DB)

엔티티 매니저가 detach하여 준영속상태가 된 customer를 조회합니다.
준영속상태이므로 1차 캐시에 customer정보가 없습니다.
따라서 DB에서 정보를 가져와 1차 캐시에 저장하고 이를 반환합니다.

고객 조회 테스트 (1차 캐시)

영속상태인 customer를 조회하므로 1차 캐시에서 정보를 찾아 이를 반환합니다.
따라서 db에 select 쿼리를 사용하지 않고 정보를 가져올 수 있습니다.

profile
개발자가 되어가는 중...

0개의 댓글