영속성 콘텍스트란❓
영속성(persistent)을 직역한다면 한글로 번역하면 영속성, 지속성이라는 뜻이 됩니다.
Persistence를 객체의 관점으로 해석해 보자면 ‘객체가 생명(객체가 유지되는 시간)이나 공간(객체의 위치)을 자유롭게 유지하고 이동할 수 있는 객체의 성질’을 의미합니다.
영속성 콘텍스트(Persistence Context)는 Java Persistence API (JPA)에서 엔티티의 생명 주기와 상태를 관리하는 중요한 개념입니다.
쉽게 표현해 보자면 다음과 같습니다.
- Entity 객체를 효율적으로 쉽게 관리하기 위해 서버와 DB사이의 만들어진 공간입니다.
- Entity 객체를 관리하는 일종의 메모리 캐시
ORM이 등장하면서 개발자들을 복잡하게 직접 데이터베이스에 관여하지 않고 JPA를 사용하여 DB 작업을 할 수 있게 되었다고 알고 있습니다.
이러한 일련의 과정을 효율적으로 처리하기 위해 JPA는 영속성 콘텍스트에 Entity 객체들을 저장하여 관리하면서 DB와 소통합니다.
EntityManger❓
영속성 콘텍스트에 접근하여 Entity 객체들을 조작하기 위해서는 EntityManager가 필요합니다.
EntityManager는 이름 그대로 Entity를 관리하는 관리자입니다.
데이터베이스와 객체 간의 직접적인 상호작용을 담당하며, 엔티티 객체를 영속 상태로 만들고, 데이터베이스 쿼리를 실행하며, 트랜잭션을 관리합니다.
데이터베이스 작업을 수행하는 데 있어 핵심적인 역할을 하는 객체이며, EntityManger를 통해 Entity를 저장, 조회, 수정, 삭제(CRUD) 할 수 있습니다.
EntityManger의 주요 메서드
em.persist(employee);
- persist(Object entity)
- Entity 객체를 영속성 콘텍스트에 추가합니다.
- 이 메서드를 호출하면 Entity가 영속 상태로 전환되며, 트랜잭션이 커밋될 때 데이터베이스에 저장됩니다.
- 리턴 타입: void
Employee mergedEmployee = em.merge(employee);
- merge(Object entity)
- 주어진 Entity의 상태를 현재 영속성 컨텍스트에 병합합니다.
- 이미 영속성 컨텍스트에
존재하지 않는엔티티의 상태를 업데이트할 때 사용됩니다. - 리턴 타입: 병합된 엔티티 인스턴스
em.remove(employee);
- remove(Object entity)
- 영속성 콘텍스트에서 Entity를 제거합니다.
- 이 메서드는 엔티티를 데이터베이스에서 "삭제할 준비"를 합니다.
- 리턴 타입: void
Employee employee = em.find(Employee.class, 1L);
- find(Class <T> entityClass, Object primaryKey)
- 주어진 클래스 타입과 기본 키를 사용하여 엔티티를 검색합니다.
- 기본 키로 엔티티를 찾는 데 사용됩니다.
- 리턴 타입: T (찾은 Entity 인스턴스)
Employee employee = em.getReference(Employee.class, 1L);
- getReference(Class <T> entityClass, Object primaryKey)
- 주어진 클래스 타입과 기본 키를 사용하여 Entity에 대한 참조를 반환합니다.
- 엔티티는
실제로 로드되지 않고, 지연 로딩된 프락시가 반환됩니다. - 리턴 타입: T (프락시 또는 실제 엔티티)
TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e", Employee.class);
List<Employee> employees = query.getResultList();
- createQuery(String jpql)
- JPQL(Java Persistence Query Language) 쿼리를 생성합니다.
- JPQL 쿼리는 객체 모델을 기반으로 데이터베이스 쿼리를 작성하는 데 사용됩니다.
- 리턴 타입: TypedQuery <T> (JPQL 쿼리)
TypedQuery<Employee> query = em.createNamedQuery("Employee.findAll", Employee.class);
List<Employee> employees = query.getResultList();
- createNamedQuery(String name)
- 이름으로 정의된 JPQL 쿼리를 생성합니다.
- 이 쿼리는 @NamedQuery 어노테이션으로 정의된 쿼리입니다.
- 리턴 타입: TypedQuery<T>
Query query = em.createNativeQuery("SELECT * FROM employee");
List<Object[]> results = query.getResultList();
- createNativeQuery(String sql)
- 네이티브 SQL 쿼리를 생성합니다.
- 이 메서드는 SQL 쿼리를 직접 작성하여 데이터베이스 작업을 수행할 때 사용됩니다.
- 리턴 타입: Query
EntityTransaction tx = em.getTransaction();
tx.begin();
// 데이터베이스 작업 수행
tx.commit();
- getTransaction()
- 현재 트랜잭션을 반환합니다.
- 트랜잭션 관리를 통해 데이터베이스 작업을 커밋하거나 롤백할 수 있습니다.
- 리턴 타입: EntityTransaction
em.flush();
- flush()
- 영속성 컨텍스트의 변경 사항을 데이터베이스에 동기화합니다.
- flush()는 트랜잭션이 커밋되기 전에 변경 사항을 즉시 데이터베이스에 반영합니다.
- 리턴 타입: void
em.clear();
- clear()
- 영속성 컨텍스트의 모든 엔티티를 제거합니다.
- 이는 엔티티의 영속성 상태를 비워, 영속성 컨텍스트를 초기화합니다.
- 리턴 타입: void
em.detach(employee);
- detach(Object entity)
- 영속성 컨텍스트에서 특정 엔티티를 분리합니다.
- 분리된 엔티티는 더 이상
영속성 컨텍스트의 관리하에 있지 않으며,데이터베이스와의 동기화도 이루어지지 않습니다. - 리턴 타입: void
EntityMangerFactory란❓
EntityManagerFactory는 EntityManager를 생성하는 팩토리 객체로, 애플리케이션의 전체 lifecycle(동작)하는 동안 데이터베이스 설정과 리소스를 관리합니다.
EntityManagerFactory는 일반적으로 DB 하나에 하나만 생성되어 애플리케이션이 전체 lifecycle(동작)하는 동안 사용됩니다.
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="???">
<properties>
<property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jakarta.persistence.jdbc.user" value="root"/>
<property name="jakarta.persistence.jdbc.password" value="{비밀번호}"/>
<property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/memo"/>
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
</properties>
</persistence-unit>
</persistence>
EntityManagerFactory를 만들기 위해서는 DB에 대한 정보를 전달해야 합니다.
정보를 전달하기 위해서는 /resources/META-INF/ 위치에 persistence.xml 파일을 만들어 정보를 넣어두면 됩니다.
Persistence라는 클래스에 의해서 persistence.xml 파일을 읽고 DB의 정보를 가지고 EntityMangerFactory를 만들어지게 되고, 이어서 EntityManger가 생성이 됩니다.
hibernate.show_sql
<property name="hibernate.show_sql" value="true"/>
hibernate.show_sql 속성을 true로 설정하면 Hibernate가 실행하는 SQL 쿼리가 콘솔에 출력됩니다.
EntityMangerFactory 주요 메서드 ✅
EntityManager em = emf.createEntityManager();
- createEntityManager()
- 새로운 EntityManager 인스턴스를 생성합니다.
- 리턴 타입: EntityManager
Map<String, Object> properties = new HashMap<>();
properties.put("javax.persistence.jdbc.url", "jdbc:mysql://localhost:3306/mydatabase");
EntityManager em = emf.createEntityManager(properties);
- createEntityManager(Map<String, Object> properties)
- 추가적인 설정을 포함하여 EntityManager 인스턴스를 생성합니다.
- 설정은 Map 형태로 제공됩니다.
- 리턴 타입: EntityManager
Cache cache = emf.getCache();
- getCache()
- 현재 EntityManagerFactory와 연관된 캐시를 반환합니다.
- 이 캐시는 엔티티 상태와 쿼리 결과를 캐싱하는 데 사용됩니다.
- 리턴 타입: Cache
CriteriaBuilder cb = emf.getCriteriaBuilder();
- getCriteriaBuilder()
- Criteria API를 사용하여 동적 쿼리를 생성하기 위한 CriteriaBuilder 객체를 반환합니다.
- 리턴 타입: CriteriaBuilder
Metamodel metamodel = emf.getMetamodel();
- getMetamodel()
- JPA 메타 모델을 반환하여 엔티티 클래스와 속성의 메타 정보를 얻을 수 있습니다.
- 리턴 타입: Metamodel
emf.close();
- close()
- EntityManagerFactory를 종료하고 모든 관련 리소스를 해제합니다.
- 더 이상 EntityManagerFactory를 사용하지 않을 때 호출해야 합니다.
Persistence클래스란❓
Persistence클래스란 JPA에서 EntityManagerFactory를 생성하는 데 사용되는 유틸리티 클래스입니다.
주요 역할
EntityManagerFactory 생성
- Persistence 클래스는 persistence.xml 파일에 정의된 "Persistence Unit"을 기반으로 EntityManagerFactory 인스턴스를 생성합니다.
- 이를 통해 JPA 환경을 설정하고, 데이터베이스와의 상호작용을 위한 EntityManagerFactory를 제공받을 수 있습니다.
주요 메서드
- createEntityManagerFactory(String persistenceUnitName)
- 주어진 Persistence Unit 이름을 기반으로 EntityManagerFactory를 생성합니다.
- createEntityManagerFactory(String persistenceUnitName, Map<String, Object> properties):
- Persistence Unit 이름과 추가적인 설정을 포함하는 프로퍼티 맵을 기반으로 EntityManagerFactory를 생성합니다.
위와 같이 Persistence 클래스 내부의 createEntityManagerFactory() 메서드는 인자로 persistenceUnitName을 받아야 합니다.
이 persistenceUnitName은 persistence.xml 파일에서 정의된 persistence-unit의 이름과 일치해야 하며, 이 이름을 사용하여 EntityManagerFactory를 올바르게 생성할 수 있습니다.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("memo");
EntityManager em = emf.createEntityManager();
그렇다면 위와 같이 JPA는 createEntityManagerFactory() 메서드를 사용하여 persistence.xml 의 정보를 토대로 EntityManagerFactory를 생성하고, EntityManagerFactory의 createEntityManger() 메서드를 사용하여 EntityManager를 생성할 수 있습니다.
트랜잭션(Transaction)란❓
트랜잭션은 데이터베이스 작업의 논리적인 단위를 정의하며, 여러 데이터베이스 연산을 하나의 단위로 묶어 처리합니다.
즉 DB 데이터들의 무결성과 정합성을 유지하기 위한 하나의 논리적 개념입니다.
트랜잭션(Transaction)의 중요성
JPA에서 트랜잭션은 다음과 같은 주요 기능을 수행합니다.
- 원자성 (Atomicity)
- 트랜잭션 내의 모든 작업이 성공적으로 완료되거나, 실패 시 모든 작업이 롤백됩니다.
- 일관성 (Consistency)
- 트랜잭션이 완료된 후 데이터베이스는 일관된 상태를 유지합니다.
- 격리성 (Isolation)
- 트랜잭션 간의 독립성을 보장하여 한 트랜잭션의 작업이 다른 트랜잭션에
영향을 미치지 않도록 합니다.
- 트랜잭션 간의 독립성을 보장하여 한 트랜잭션의 작업이 다른 트랜잭션에
- 지속성 (Durability)
- 트랜잭션이 COMMIT되면 그 결과는 영구적으로 데이터베이스에 저장됩니다.
DB에서 하나의 트랜잭션에 여러 개의 SQL을 포함하고 있다가 마지막에 영구적으로 변경을 반영합니다.
이처럼 JPA에서도 영속성 컨텍스트로 관리하고 있는 변경이 발생한 객체들의 정보를 쓰기 지연 저장소에 전부 가지고 있다가 마지막에 SQL을 한번에 DB에 요청해 변경을 반영합니다.
위와 같은 트랜잭션의 개념을 사용하여 효율적으로 Entity를 관리하고 있습니다.
'Framework > JPA' 카테고리의 다른 글
[JPA] 트랜잭션 관리와 영속성 컨텍스트의 관계 (@Transaction, 트랜잭션 전파) (0) | 2024.07.27 |
---|---|
[JPA] JPA Entity 상태 (비영속, 영속, 준영속, 삭제 상태의 이해) (0) | 2024.07.27 |
[JPA] 영속성 컨텍스트란 무엇일까❓ #2(1차 캐시, 변경 감지, 쓰기지연 감소) (0) | 2024.07.27 |
[JPA] Entity란 무엇일까❓(Entity: 데이터베이스와 자바 객체 간의 다리) (0) | 2024.07.26 |
[JPA] JPA란 무엇일까❓ (0) | 2024.07.25 |