[JPA] JPA 사용 시 주의할 점
2021. 12. 3. 17:29ㆍSpring/JPA
아래 코드를 살펴보자.
public class DepartmentRepository {
@PersistenceContext
EntityManager em;
public Department findById(Long id) {
Department dept = em.find(Department.class, id);
return dept;
}
}
findById()
는 id값으로 Department를 조회하여 해당 id의 객체를 가져온다. 그런데 이때 가져온 객체는 영속 상태일까? 결론부터 말하자면 아니다. em.find()
를 처리하는 과정은 트랜잭션으로 수행된다. 그러나 가져온 이후의 값은 영속성 컨텍스트에서 관리되는 것이 아닌 단순 객체가 되는 것이다. 따라서 가져온 후의 처리 또한 영속성 컨텍스트로 관리하기 위해서는 이 과정을 트랜잭션으로 묶어야 한다.
public class DepartmentRepository {
@PersistenceContext
EntityManager em;
public Department findById(Long id) {
try {
em.begin();
Department dept = em.find(Department.class, id);
em.commit();
return dept;
} catch (RuntimeException e) {
em.rollback();
}
}
}
그렇다면 우리는 개발할 때마다 try - catch로 모든 작업을 묶어야 해야 할까? JPA를 원초적으로 사용한다면 그렇게 해야 한다. 그러나 스프링에서는 이를 위해 @Transactional이라는 어노테이션을 제공한다. 이 어노테이션을 적용하면 해당 메서드를 수행하기 전에 트랜잭션 처리를 해준다.
@Transactional은 스프링의 AOP와 PSA의 철학을 담고 있는 기능이다.
public class DepartmentRepository {
@PersistenceContext
EntityManager em;
@Transcational
public Department findById(Long id) {
Department dept = em.find(Department.class, id);
return dept;
}
}
이 어노테이션은 클래스에도 선언할 수 있는데 이렇게 사용하면 해당 클래스의 모든 메서드에 @Transactional이 적용된다.
@Transactional
public class DepartmentRepository {
@PersistenceContext
EntityManager em;
//@Transcational
public Department findById(Long id) {
Department dept = em.find(Department.class, id);
return dept;
}
}
또한 속성으로 readOnly를 적용하면 읽기만 하는 트랜잭션임을 명시하였기 때문에 성능이 향상된다. @Transactional의 readOnly 기본값은 false이다.
@Transactional
public class DepartmentRepository {
@PersistenceContext
EntityManager em;
@Transcational(readOnly = true)
public Department findById(Long id) {
Department dept = em.find(Department.class, id);
return dept;
}
}
'Spring > JPA' 카테고리의 다른 글
[JPA] 코틀린으로 엔티티 작성 시 고려할 점 (0) | 2022.02.08 |
---|---|
[JPA] Fetch - Eager, Lazy (0) | 2021.12.04 |
[JPA] 연관관계[2/2] - 단방향 (0) | 2021.12.03 |
[JPA] 연관관계[1/2] - 양방향 (0) | 2021.12.03 |
[JPA/Hibernate] Hibernate 기초 (0) | 2021.10.12 |