EntityManager

엔터티 매니저(EntityManager)란?
엔터티 매니저는 엔터티를 저장하는 메모리상의 데이터베이스라고 생각하면 된다.
엔터티를 저장하고 수정하고 삭제하고 조회하는 등의 엔터티와 관련된 모든 일을 한다.
엔터티 매니저는 스레드세이프 하지 않기 때문에 동시성 문제가 발생할 수 있기 때문에 스레드간 공유를 하면 안된다.
 web의 경우 일반적으로는 request scope와 일치시킨다

엔티티 매니저(Entity Manager)는 JPA(Java Persistence API)에서 사용되는 개념입니다.
JPA는 자바 진영에서 제공하는 ORM(Object-Relational Mapping) 기술의 표준 인터페이스로, 데이터베이스와 객체 간의 매핑을 처리하는 라이브러리입니다.
엔티티 매니저는 JPA에서 영속성 컨텍스트(Persistence Context)를 관리하는 역할을 합니다.
영속성 컨텍스트는 엔티티(Entity) 객체와 데이터베이스 테이블 간의 매핑 정보를 유지하고, 엔티티 객체의 상태 변화를 추적하여 데이터베이스와의 동기화를 수행합니다.
따라서 엔티티 매니저는 JPA에서 영속성 컨텍스트를 생성하고, 엔티티 객체의 상태 변화를 추적하여 데이터베이스와의 동기화를 수행하는 핵심적인 역할을 수행합니다.

EntityManagerFactory

 

엔터티 매니저 팩토리(EntityManagerFactory)란?
엔터티 매니저를 생성할 수 있는 기능을 제공하는 팩토리 클래스이다.
스레드세이프이기 때문에 여러 스레드가 동시에 접근해도 안전하기 때문에 서로 다른 스레드간 공유해서 재사용한다.
하지만 스레드 세이프 한 기능을 요청 스코프마다 생성하기에는 비용(시간, 메모리)부담이 크기 때문에
application 스코프와 동일한 싱글톤으로 생성해서 관리하게 된다.
따라서 데이터베이스를 사용하는 애플리케이션 당 한 개의 EntityManagerFactory를 생성한다.

PersistenceContext

 

영속성 컨텍스트(PersistenceContext)란?
영속성 컨텍스트는 엔터티를 영구 저장하는 환경을 말한다. 
엔터티 매니저에 엔터티를 저장하거나 조회하면 엔터티 매니저는 영속성 컨텍스트에 엔터티를 보관하고 관리한다.
영속성 엔터티를 key value방식으로 저장하는 저장소 역할을 한다.
영속성 컨텍스트는 엔터티 매니저를 생성할 때 하나 만들어진다.
그리고 엔터티 매니저를 통해서 영속성 컨텍스트에 접근할 수 있고 영속성 컨텍스트를 관리할 수 있다.


공통적인 부분

	private static EntityManagerFactory entityManagerFactory;
	private EntityManager entityManager;
	
	@BeforeAll
	public static void initFactory() {
		entityManagerFactory = Persistence.createEntityManagerFactory("jpatest");
	}
	
	@BeforeEach
	public void initManager() {
		entityManager = entityManagerFactory.createEntityManager();
	}
	
	@AfterAll
	public static void closeFactory() {
		entityManagerFactory.close();
	}
	
	@AfterEach
	public void closeManager() {
		entityManager.close();
		
	}

메뉴 조회 테스트

EntityManager의 find() 메서드를 호출하여 해당 엔티티의 식별자(primary key)를 기반으로

데이터베이스에서 엔티티를 조회

 

find() 메서드의 첫 번째 인자로는 조회할 엔티티 클래스를 전달하고,

두 번째 인자로는 조회할 엔티티의 식별자 값을 전달한다

따라서 주어진 코드에서는 EntityManager의 find() 메서드를 호출하여 Menu 클래스에 해당하는 엔티티를 조회하고,

조회된 결과를 foundMenu 변수에 저장한다.

이때, menuCode 변수에는 조회할 엔티티의 식별자 값인 2가 전달 된다.

entityManager.find(Menu.class, menuCode);

foundMene가 null이 아닐때, 테스트 케이스의 검증(verification)을 위해 assert 문을 사용한다.

assertNotNull() 메서드는 해당 객체가 null이 아님을 검증한다. 그리고

foundMenu 객체의 getMenuCode() 메서드를 사용하여 해당 메뉴의 메뉴코드가 menuCode 값(2)과 동일한지 검증한다.

		assertNotNull(foundMenu);
		assertEquals(menuCode, foundMenu.getMenuCode());

 

메뉴 추가 테스트

setter를 사용하여 추가할 메뉴의 name과 price 등을 설정 한다.

		//given
		Menu menu = new Menu();
		menu.setMenuName("JPA 테스트용 신규 메뉴");
		menu.setMenuPrice(5000);
		menu.setCategoryCode(4);
		menu.setOrderableStatus("Y");

 

 

EntityTransaction

 

EntityManager의 getTransaction() 메서드는 JPA에서 사용되는 데이터베이스 트랜잭션(Transaction) 처리를 위한 EntityTransaction 객체를 반환한다.

EntityTransaction 객체는 JPA에서 데이터베이스 트랜잭션을 처리하기 위한 인터페이스로,

begin(), commit(), rollback() 메서드를 제공한다.

따라서 주어진 코드에서는 EntityManager의 getTransaction() 메서드를 호출하여 EntityTransaction 객체를 얻어온 후, 이를 entityTransaction 변수에 할당하고, 

이후에는 이 EntityTransaction 객체를 사용하여 데이터베이스 트랜잭션을 처리한다.

		EntityTransaction entityTransaction = entityManager.getTransaction();
		entityTransaction.begin();

또한 try-catch문을 사용하여 오류가 나지 않는다면 menu에 commit을 하게 되고,

만약 오류가 난다면 rollback을 실행한다.

		try {
			entityManager.persist(menu);
			entityTransaction.commit();
		} catch (Exception e) {
			entityTransaction.rollback();
			e.printStackTrace();
		}

> 마지막으로 assertTrue까지 실행해서 검증해 보기!

assertTrue(entityManager.contains(menu));

메뉴 이 수정 테스트

메뉴 이름 수정테스트도 거의 동일하다.

Menu에 2번째 code가 무엇인지 일단 파악한다.

		Menu menu = entityManager.find(Menu.class, 2);
		System.out.println("menu = " + menu);

바꿀 MenuName을 적고 EntityTransaction을 이용하여 바꿔준다.

		String menuNameToChange = "우럭스무디";
		
		//when
		EntityTransaction entityTransaction = entityManager.getTransaction();
		entityTransaction.begin();

> 마지막으로 assertEquals 까지 실행해서 검증해 보기!

assertEquals(menuNameToChange, entityManager.find(Menu.class, 2).getMenuName());

메뉴 삭제 테스트

 

주어진 코드에서는 EntityManager의 find() 메서드를 사용하여 Menu 클래스에 해당하는 엔티티를 조회하고, 조회된 결과를 menuToRemove 변수에 할당한다. 이때, 1번 메뉴를 조회하여 삭제 대상으로 설정하고,

 

이후에 EntityManager의 getTransaction() 메서드를 호출하여 EntityTransaction 객체를 얻어온 후, 데이터베이스 트랜잭션을 시작한다. try-catch 블록에서는 entityManager의 remove() 메서드를 사용하여 menuToRemove 엔티티를 데이터베이스에서 삭제하고, entityTransaction.commit() 메서드를 호출하여 데이터베이스 트랜잭션을 커밋한다. 만약 예외가 발생하면 entityTransaction.rollback() 메서드를 호출하여 데이터베이스 트랜잭션을 롤백하도록 한다.

 

마지막으로 EntityManager의 find() 메서드를 사용하여 삭제된 엔티티를 조회하고, assertNull() 메서드를 사용하여 해당 엔티티가 존재하지 않음을 검증하게 된다.

		//given
		Menu menuToRemove = entityManager.find(Menu.class, 1);
		
		//when
		EntityTransaction entityTransaction = entityManager.getTransaction();
		entityTransaction.begin();
		
		try {
			entityManager.remove(menuToRemove);
			entityTransaction.commit();
		} catch (Exception e) {
			entityTransaction.rollback();
			e.printStackTrace();
		}
		
		//then
		Menu removedMenu = entityManager.find(Menu.class, 1);
		assertEquals(null, removedMenu);

여기까지 JPA를 알아보았다!

 

SMALL

+ Recent posts