JPA

JPAQueryFactory를 필드에서 제공하자(feat. 동시성 문제는 스프링이 해결)

쿠카이든 2022. 2. 14. 12:14
728x90
  • (Java JPA) JPAQueryFactory를 필드로 제공할 때, 동시성 문제
    • (As-is) → 기존 JPAQueryFactory를 메소드 안에 생성한 버전
@SpringBootTest
@Transactional
public class QuerydslBasicTest {
    @PersistenceContext
    EntityManager em;

    @Test
    public void startQuerydsl() {
    
        JPAQueryFactory queryFactory = new JPAQueryFactory(em); //JPAQueryFactory를 메소드 안에 생성
        QMember m = new QMember("m");
    
        Member findMember = queryFactory
            .select(m)
            .from(m)
            .where(m.username.eq("member1"))//파라미터 바인딩 처리
            .fetchOne();
            
        assertThat(findMember.getUsername()).isEqualTo("member1");
    
}
  • 소스 설명
    • EntityManager 로 JPAQueryFactory 생성한 후,
    • 기존에는 메소드 안에 JPAQueryFactory객체를 생성하였습니다.
  • (To-Be) → JPAQueryFactory를 필드에 정의한 버전
@SpringBootTest
@Transactional
public class QuerydslBasicTest {
    @PersistenceContext
    EntityManager em;
    
    JPAQueryFactory queryFactory;   //JPAQueryFactory을 필드에 정의
    
    @BeforeEach
    public void before() {
        queryFactory = new JPAQueryFactory(em);
        //…
    }
    
    @Test
    public void startQuerydsl2() {

        //JPAQueryFactory가 공통 필드에 정의됨 -> 테스트가 여러개일 때, 생략 가능!! 
        QMember m = new QMember("m");
      
        Member findMember = queryFactory
           .select(m)
           .from(m)
           .where(m.username.eq("member1"))
           .fetchOne();
       assertThat(findMember.getUsername()).isEqualTo("member1");
   }
}
  • JPAQueryFactory를 필드에 정의하면 위 소스와 같습니다.
    • 여러 메소드에서 호출할 때, 동시성 문제는?
      • 동시성 문제는 JPAQueryFactory를 생성할 때 제공하는 EntityManager(em)에 달려있습니다.
      • 스프링 프레임워크는 여러 쓰레드에서 동시에 같은 EntityManager에 접근해도, 트랜잭션 마다 별도의 영속성 컨텍스트를 제공하기 때문에, 동시성 문제는 걱정하지 않아도 됩니다(스프링 프레임워크 차원에서 해결됨).
728x90