Java / Spring

[QueryDsl] Repository(custom) 구현 본문

Spring/Spring Data JPA

[QueryDsl] Repository(custom) 구현

밍구밍구밍 2024. 11. 18. 15:23


querydsl 을 사용하여 프로젝트를 진행하면서 이해가 되지 않았던 부분 복습을 위한 기록

@Repository
@Transactional
public class EmployRepositoryImpl extends QuerydslRepositorySupport implements EmployeeRepositoryCustom {

    private final JPAQueryFactory jpaQueryFactory;

    public EmployRepositoryImpl(EntityManager entityManager) {
        super(Employee.class);
        jpaQueryFactory = new JPAQueryFactory(entityManager);
    }

 

먼저 QueryDsl 기능을 사용하기 위해 EmployeeRepositoryCustom 라는 인터페이스를 구현한  EmployeeRepositoryImpl   리포지토리 클래스를 생성한다.

 

EmployeeRepositoryCustom 인터페이스는 아래와 같이 정의 하였다.

@Repository
public interface EmployeeRepositoryCustom {

    DepartmentDTO findByEmpDepartInfo(Integer id);

    AttendanceDTO findByOneEmpAttInfo(Integer id);

    Page<AttendanceDTO> findByAllEmpAttInfo(Integer id, LocalDate attDate, PageRequest pageRequest);
}

 

EmployeeRepositoryImpl 에서 정의한 코드를 하나씩 살펴보면,

@Repository : 해당 클래스를 Spring Bean 으로 등록하기 위한 어노테이션 설정

@Transactional : 트랜잭션 관리를 위해 클래스 내의 메서드들은 모두 하나의 트랜잭션으로 묶여 실행될 수 있도록 설정

 

클래스의 상속과 인터페이스 구현 관계

- extends QuerydslRepositorySupport : 이 클래스는 QueryDSL을 사용하기 위한 지원 클래스이다. 해당 클래스를 상속하게 되면 QueryDSL 쿼리를 작성할 떄 필요한 기능을 사용 할수있다.

> JPAQueryFactory 사용 가능

 

implements EmployeeRepositoryCustom : 위에서 정의한 인터페이스 내에 구현한 메서드 @Override 로 현재 클래스에서 기능 구현

> findByEmpDepartInfo(), findByOneEmpAttInfo(), findByAllEmpAttInfo()

 

먼저 querydsl 에서 JPA를 사용하여 쿼리를 생성하고 jpql 쿼리를 사용하기 위한 JPAQueryFactory 객체를 선언한다

private final JPAQueryFactory jpaQueryFactory;

 

추가로 해당 클래스의 생성자를 통해 EntityManager 를 내부 파라미터로 초기화 하고 Dependency Injection 으로 객체를 주입하도록 설정한다.

public EmployRepositoryImpl(EntityManager entityManager) {
    super(Employee.class);
    jpaQueryFactory = new JPAQueryFactory(entityManager);
}

- EntityManager : JPA에서 데이터베이스와 상호작용을 담당하는 핵심 객체

- super(Employee.class) : QueryRepositorySuppory 는 Employee.class 를 매개변수로 받는 생성자가 있고, 이를 통해 기본적으로 Employee 라는 엔티티와 관련된 쿼리를 생성하는 데 사용할 수 있는 환경을 초기화 한다.

 

생성자 내부에서는 위에서 객체로 초기화한 JPAQueryFactory 의 인스턴스에 EntityManager 의 인스턴스를 파라미터로 받는JPAQueryFactory 를 인스턴스 변수에 할당한다. 이렇게 되면 jpaQueryFactory 인스턴스를 사용하여 실제 QueryDSL 쿼리 (select, from, join 등)을 구현할 수 있게 된다.

 

사용 예) 사원의 id를 입력하여 해당 사원의 부서정도를 조회하는 쿼리

@Override
public DepartmentDTO findByEmpDepartInfo(Integer id) {
    return jpaQueryFactory.select(new QDepartmentDTO(department.id,
                    department.deptCode,
                    department.deptName,
                    employee.id, employee.empName))
            .from(department)
            .join(department.employees, employee)
            .where(employee.id.eq(id))
            .fetchOne();
}