Loading...

Spring / / 2022. 5. 10. 16:44

EntityManager Transaction

반응형

EntityManager로 이런것도 할 수 있다.

 

createQuery는 내부적으로 영속화 된 엔티티를 리턴해준다.

Query query = em.createQuery("SELECT * FROM post"); // 내부적으로 영속화 됨

 

Repository에서 쿼리를 만들었었는데

jpa는 내부적으로 EntityManager를 쓰고있네.

 

PostRepository는 Post 오브젝트만 관리해서

Post만 리턴할 수 있다는 단점이있다.

 

서브쿼리, 피벗 등 복잡한 쿼리를 짜면 절대 Post 오브젝트로만(지정해둔 타입) 리턴되지 않기 때문에 불편하다.

 

JPQL을 사용해보자.

JPQL(Java Persistence Query Langauge)

JPA는 내부적으로 JPQL로 만들어져있다.

API라서 findById와 같이 만들어져있는 메서드를 사용했다.

 

JPQL이 prepareStatement와 똑같은데 영속화를 시켜준다는 차이점이 있다.

 

JPQL은 언제 사용할까?

1. 복잡한 쿼리를 사용할 때 (통계쿼리와 같이)

2. Dto로 리턴 받고 싶을 때 

 

컨트롤러에서 emTest1을 때리면 postEntity를 리턴받는다.

대신 repository를 타지 않는다!!

// JPQL : Java Persistence Query Langauge
public Post emTest1() {
    TypedQuery<Post> query = em.createQuery("SELECT * FROM post WHERE id = 1", Post.class); // 내부적으로 영속화 됨
    Post postEntity = query.getSingleResult();
    return postEntity; // 대신에 repository를 타지 않는다!
}

 

em을 사용하면 트랜잭션 관리도 직관적으로 할 수 있다.

// JPQL : Java Persistence Query Langauge
public Post emTest1() {
    em.getTransaction().begin(); // 트랜잭션 시작
    TypedQuery<Post> query = em.createQuery("SELECT * FROM post WHERE id = 1", Post.class); // 내부적으로 영속화 됨
    Post postEntity = query.getSingleResult();
    em.close(); // 트랜잭션 종료

    return postEntity; // 대신에 repository를 타지 않는다!
}

 

@Transactional 어노테이션의 내부는 이런 구조인것이다.

// JPQL : Java Persistence Query Langauge
public Post emTest1() {
    em.getTransaction().begin(); // 트랜잭션 시작
    TypedQuery<Post> query = em.createQuery("SELECT * FROM post WHERE id = 1", Post.class); // 내부적으로 영속화 됨
    Post postEntity = query.getSingleResult();

    try {
        // insert()

        // update()

        em.getTransaction().commit();
    } catch (RuntimeException e) {
        em.getTransaction().rollback();
    }

    em.close(); // 트랜잭션 종료

    return postEntity; // 대신에 repository를 타지 않는다!
}

 

@Transactional 어노테이션은 무조건 RuntimeException을 탈때만 rollback 한다.

 

이때 어노테이션에 rollbackFor를 걸어줘서 어떤 Exception이 터졌을때 rollback할지 지정해줄 수 있다.

이는 위 코드에서 캐치문에 RuntimeException을 설정해주는게 아닌 CustomApiException을 걸어주는것과 같다.

 

@Transactional(rollbackFor = CustomApiException.class)
=
catch (CustomApiException e)

 

 

 

[출처]

 

https://cafe.naver.com/metacoding

 

메타코딩 : 네이버 카페

코린이들의 궁금증

cafe.naver.com

메타 코딩 유튜브

https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9

 

메타코딩

문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com

www.youtube.com

 
반응형