Persistence Context
1. EntityManager
엔터티 매니저는 엔터티를 저장하는 메모리 상의 데이터베이스로,
엔터티 저장, 수정, 삭제, 조회 등 엔터티와 관련된 모든 일을 한다.
EntityManagerFactory를 통해 만들어진다.
엔터티 매니저는 스레드 세이프하지 않기 때문에 동시성 문제가 발생할 수 있어 스레드 간 공유를 하면 안되고,따라서 web의 경우 일반적으로 request scope와 일치시킨다. (하나의 요청을 하나의 엔터티 매니저를 통해 관리)이와 비슷하게 MyBatis에서 sqlSession도 스레드 세이프하지 않기 때문에 하나의 요청 당 하나의 sqlSession을 만들었다.
2. EntityManagerFactory
엔터티 매니저를 생성할 수 있는 기능을 제공한다.스레드 세이프하기 때문에 여러 스레드가 동시 접근해도 안전하므로 서로 다른 스레드 간 공유해서 재사용한다.요청 스코프에서도 application 스코프와 동일한 싱글톤으로 생성해서 관리하므로DB를 사용하는 애플리케이션 당 하나의 entityManagerFactory를 생성한다.
3. PersistenceContext
엔터티를 영구 저장하는 환경으로, 영속성 컨텍스트라 한다.
엔터티 매니저에 엔터티를 저장하거나 조회하면 엔터티 매니저는 영속성 컨텍스트에 엔터티를 보관하고 관리하는데,
영속성 엔터티를 key value 방식으로 저장하는 저장소 역할을 한다.
엔터티 매니저를 하나 생성하면 영속성 컨텍스트도 하나 만들어지고
엔터티 매니저는 영속성 컨텍스트를 관리하게 된다. (딸려있는 느낌)
실습 - PersistenceContext 관련 생성 확인하기
* 디렉토리 구조
* DB 연결 설정
<!--/main/resources/META-INF/persistence.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2">
<!-- 엔티티 매니저 팩토리를 식별하기 위한 이름 설정 -->
<persistence-unit name="jpatest">
<!--현재 실습은 Spring이 아닌 Java 환경이기 때문에
아래서 만들 엔터티를 persistence.xml에 추가해줘야 한다.-->
<class>org.example.section02.crud.Menu</class>
<class>org.example.section03.entity.Menu</class>
<properties>
<!-- 데이터 베이스 연결 정보 -->
<property name="jakarta.persistence.jdbc.driver" value="org.mariadb.jdbc.Driver"/>
<property name="jakarta.persistence.jdbc.url" value="jdbc:mariadb://localhost:3306/menudb"/>
<property name="jakarta.persistence.jdbc.user" value="swcamp"/>
<property name="jakarta.persistence.jdbc.password" value="swcamp"/>
<!-- hibernate 설정 (실행 되는 sql 구문을 format 형태로 보여준다) -->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
* EntityManagerFactoryGenerator와 EntityManagerGenerator 클래스
package org.example.section01.entitymanager;
public class EntityManagerFactoryGenerator {
// static: 하나만 만들겠다
// 괄호 안에는 persistence.xml의 persistence-unit 태그의 name이 들어가야 한다.
private static EntityManagerFactory factory
= Persistence.createEntityManagerFactory("jpatest");
// 생성자를 private로 (싱글톤)
private EntityManagerFactoryGenerator() {}
public static EntityManagerFactory getInstance() {
return factory;
}
}
package org.example.section01.entitymanager;
public class EntityManagerGenerator {
public static EntityManager getInstance() {
EntityManagerFactory factory = EntityManagerFactoryGenerator.getInstance();
return factory.createEntityManager();
}
}
* 테스트 코드 작성
package org.example.section01.entitymanager;
public class EntityManagerGeneratorTest {
@Test
@DisplayName("엔터티 매니저 팩토리 생성 확인")
void testGenerateEntityManagerFactory() {
//given
//when
EntityManagerFactory factory = EntityManagerFactoryGenerator.getInstance();
//then
// null이면 DB와 연결이 안된 것
assertNotNull(factory);
}
@Test
@DisplayName("엔터티 매니저 팩토리 싱글톤 인스턴스 확인")
void testIsEntityManagerFactorySingletonInstance() {
//given
//when
EntityManagerFactory factory1 = EntityManagerFactoryGenerator.getInstance();
EntityManagerFactory factory2 = EntityManagerFactoryGenerator.getInstance();
//then
assertEquals(factory1, factory2);
assertEquals(factory1.hashCode(), factory2.hashCode());
}
@Test
@DisplayName("엔터티 매니저 생성 확인")
void testGenerateEntityManager() {
//given
//when
EntityManager entityManager = EntityManagerGenerator.getInstance();
//then
assertNotNull(entityManager);
}
@Test
@DisplayName("엔터티 매니저 스코프 확인")
void testEntityManagerLifeCycle() {
//given
//when
EntityManager entityManager1 = EntityManagerGenerator.getInstance();
EntityManager entityManager2 = EntityManagerGenerator.getInstance();
//then
assertNotEquals(entityManager1, entityManager2);
assertNotEquals(entityManager1.hashCode(), entityManager2.hashCode());
}
}
'Spring Framework > JPA' 카테고리의 다른 글
[JPA] 6. Association Mapping (6) | 2024.09.17 |
---|---|
[JPA] 5. Mapping (0) | 2024.09.16 |
[JPA] 4. EntityLifeCycle (6) | 2024.09.13 |
[JPA] 3. CRUD 실습 (0) | 2024.09.13 |
[JPA] 1. 개요 및 개발환경 구축 (0) | 2024.09.13 |