티스토리 뷰
PersistenceContext에 대한 설명
@PersistenceContext는 JPA(Java Persistence API)에서 Entity Manager(엔터티 매니저)를 주입할 때 사용되는 애너테이션입니다. 이는 JPA에서 데이터베이스 작업을 수행하는 핵심 객체인 EntityManager를 관리하는 데 도움을 줍니다.
1. @PersistenceContext의 역할
@PersistenceContext는 JPA의 영속성 컨텍스트(Persistence Context)를 관리하는 역할을 합니다. 영속성 컨텍스트는 JPA에서 엔터티 객체(Entity)를 관리하고 데이터베이스와의 동기화를 담당하는 캐시 영역입니다.
주요 기능
- EntityManager 주입
- @PersistenceContext를 사용하면 EntityManager를 자동으로 주입받을 수 있습니다.
- 엔터티 상태 관리
- 엔터티를 persist, merge, remove, find 등의 메서드를 통해 관리할 수 있습니다.
- 트랜잭션과 함께 동작
- 영속성 컨텍스트는 기본적으로 트랜잭션과 함께 동작하며, 트랜잭션이 종료될 때 변경 사항을 자동으로 데이터베이스에 반영합니다.
2. @PersistenceContext 사용 방법
예제 1: 기본적인 @PersistenceContext 사용
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager entityManager;
public User findUserById(Long id) {
return entityManager.find(User.class, id);
}
public void saveUser(User user) {
entityManager.persist(user);
}
public void deleteUser(User user) {
entityManager.remove(user);
}
}
설명
- @PersistenceContext를 사용하여 EntityManager를 자동으로 주입받습니다.
- find()를 사용하여 특정 ID의 User 엔터티를 조회할 수 있습니다.
- persist()를 사용하여 새로운 User 엔터티를 저장합니다.
- remove()를 사용하여 엔터티를 삭제할 수 있습니다.
예제 2: @PersistenceContext와 트랜잭션 관리
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@PersistenceContext
private EntityManager entityManager;
@Transactional
public void updateUser(Long id, String newName) {
User user = entityManager.find(User.class, id);
if (user != null) {
user.setName(newName);
}
}
}
설명
- @Transactional을 사용하여 메서드가 트랜잭션 내에서 실행되도록 합니다.
- 트랜잭션이 종료될 때 변경된 엔터티가 자동으로 데이터베이스에 반영됩니다.
3. @PersistenceContext와 @Autowired의 차이점
JPA에서 EntityManager를 주입받을 때 @PersistenceContext와 @Autowired를 비교하면 다음과 같은 차이점이 있습니다.
애너테이션 주요 특징
@PersistenceContext | JPA의 표준 방식으로 EntityManager를 주입하며, 트랜잭션과 연계된 영속성 컨텍스트를 관리합니다. |
@Autowired | Spring의 DI(의존성 주입) 방식이며, Spring이 관리하는 EntityManager 또는 EntityManagerFactory를 주입할 수 있습니다. |
예제 3: @Autowired를 사용한 EntityManager 주입
import jakarta.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
private final EntityManager entityManager;
@Autowired
public UserRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
설명
- @Autowired를 사용할 수도 있지만, 일반적으로 JPA에서는 @PersistenceContext를 사용하는 것이 권장됩니다.
4. @PersistenceContext 속성
@PersistenceContext에는 type과 unitName이라는 속성이 있습니다.
속성 설명
type | 영속성 컨텍스트의 범위를 지정합니다. (PersistenceContextType.TRANSACTION 또는 PersistenceContextType.EXTENDED) |
unitName | 특정 persistence-unit을 지정할 때 사용됩니다. (기본적으로 하나만 사용하면 생략 가능) |
예제 4: @PersistenceContext의 type 속성 사용
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
- PersistenceContextType.TRANSACTION (기본값): 트랜잭션 범위 내에서 EntityManager를 공유합니다.
- PersistenceContextType.EXTENDED: 트랜잭션이 종료되더라도 EntityManager가 유지되며, 긴 세션(Long Session) 패턴을 사용할 때 유용합니다.
5. @PersistenceContext 사용 시 주의할 점
- 트랜잭션 범위를 고려해야 합니다.
- @PersistenceContext가 적용된 EntityManager는 기본적으로 트랜잭션 범위 내에서만 유효합니다.
- 트랜잭션이 종료되면 영속성 컨텍스트가 종료되므로, 트랜잭션 외부에서 엔터티를 수정해도 데이터베이스에 반영되지 않습니다.
- 스프링 @Transactional과 함께 사용해야 합니다.
- JPA의 EntityManager는 기본적으로 트랜잭션과 함께 동작하므로, @Transactional 없이 persist(), merge() 등의 메서드를 호출하면 예외가 발생할 수 있습니다.
- 영속성 컨텍스트를 올바르게 관리해야 합니다.
- PersistenceContextType.EXTENDED를 사용할 경우, EntityManager가 길게 유지될 수 있어 메모리 관리에 주의해야 합니다.
- 일반적으로 PersistenceContextType.TRANSACTION을 사용하는 것이 좋습니다.
- 스프링 데이터 JPA 사용 시 @PersistenceContext는 거의 필요하지 않습니다.
- 스프링 데이터 JPA에서는 JpaRepository 또는 CrudRepository를 사용하면 EntityManager를 직접 사용할 필요 없이 편리하게 CRUD 작업을 수행할 수 있습니다.
6. 요약
- @PersistenceContext는 JPA에서 EntityManager를 주입하는 표준 방식입니다.
- EntityManager를 통해 엔터티의 저장, 조회, 수정, 삭제 등의 작업을 수행할 수 있습니다.
- 기본적으로 트랜잭션 범위 내에서만 유효하며, @Transactional과 함께 사용해야 합니다.
- PersistenceContextType.EXTENDED를 사용하면 트랜잭션이 종료된 후에도 EntityManager를 유지할 수 있지만, 메모리 관리를 신경 써야 합니다.
- 스프링 데이터 JPA를 사용하면 JpaRepository를 통해 EntityManager를 직접 사용하지 않아도 대부분의 CRUD 작업을 처리할 수 있습니다.