[JPA] JPA 사용 시 주의할 점

2021. 12. 3. 17:29Spring/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