본문 바로가기
BackEnd

[JPA] Spring과 JPA-3

by mizuiro 2024. 7. 31.

Spring data jpa Query method

기존 jpa를 활용하면 등록, 수정, 삭제, 상세조회 외에도 상세한 검색 필터가 필요하다

이때 JPQL을 사용하면 되지만 JPQL은 따로 배워야 하고 jpa 보다 불편하다

그래서 최대한 JPQL을 직접 사용하지 않고 검색 필터를 사용할 수 있도록 쿼리 메소드라는 기능이 생성되었다

쿼리 메소드 : 스프링에서 제공하는 기능으로 메소드 이름을 기반으로 JPQL 쿼리를 생성

1. 쿼리 메소드

쿼리 메소드의 작명으로 자동으로 JPQL 쿼리를 생성한다

검색기능의 가장 대표적인 것은 find 이다

find + 엔티티 이름 + By + 변수 이름

ex) findEmployeeByName(String searchKeyword) : Employee 객체 중에서 name 변수 값이 searchKeyword 인 객체 검색

이때 엔티티 이름은 생략 할 수 있다 그러면 이때에는 리포지터리 인터페이스에 조건으로 선언한 것을 기준으로 엔티티를 설정해여 검색을 한다

public interface EmployeeRepository extends CrudRepository<Employee, Long> {

}

리턴 타입 : List, Page(paging 처리) , Slice

2. 쿼리 메소드 사용

public interface EmployeeRepository extends CrudRepository<Employee, Long> {
	List<Employee> findByName(String name); // query method사용
}

public List<Employee> getEmployeeList(Employee employee) {
		return (List<Employee>) empRepository.findByName(employee.getName()); // findAll() 에서 조건을 건 쿼리 메소드로 변환
	}
	

private static void selectData(EmployeeService employeeService) {
		Employee employee = new Employee();
		employee.setName("개발직원 3");	
		List<Employee> resultList = employeeService.getEmployeeList(employee);
		
		System.out.println("직원 목록");
		for (Employee result : resultList) {
			System.out.println("--> " + result.toString());
		}
	}

리포지토리에 findByName이라고 설정을 하여서 서비스에서 이 것을 사용할 수 있도록 한다

결과

Hibernate: 
    select
        employee0_.id as id1_1_,
        employee0_.DEPT_ID as dept_id5_1_,
        employee0_.MAIL_ID as mail_id2_1_,
        employee0_.name as name3_1_,
        employee0_.salary as salary4_1_ 
    from
        S_EMP employee0_ 
    where
        employee0_.name=?
Hibernate: 
    select
        department0_.DEPT_ID as dept_id1_0_0_,
        department0_.name as name2_0_0_,
        employeeli1_.DEPT_ID as dept_id5_1_1_,
        employeeli1_.id as id1_1_1_,
        employeeli1_.id as id1_1_2_,
        employeeli1_.DEPT_ID as dept_id5_1_2_,
        employeeli1_.MAIL_ID as mail_id2_1_2_,
        employeeli1_.name as name3_1_2_,
        employeeli1_.salary as salary4_1_2_ 
    from
        S_DEPT department0_ 
    left outer join
        S_EMP employeeli1_ 
            on department0_.DEPT_ID=employeeli1_.DEPT_ID 
    where
        department0_.DEPT_ID=?
Hibernate: 
    select
        department0_.DEPT_ID as dept_id1_0_0_,
        department0_.name as name2_0_0_,
        employeeli1_.DEPT_ID as dept_id5_1_1_,
        employeeli1_.id as id1_1_1_,
        employeeli1_.id as id1_1_2_,
        employeeli1_.DEPT_ID as dept_id5_1_2_,
        employeeli1_.MAIL_ID as mail_id2_1_2_,
        employeeli1_.name as name3_1_2_,
        employeeli1_.salary as salary4_1_2_ 
    from
        S_DEPT department0_ 
    left outer join
        S_EMP employeeli1_ 
            on department0_.DEPT_ID=employeeli1_.DEPT_ID 
    where
        department0_.DEPT_ID=?
  1. 첫번째 select 문은 findbyName을 실행하기 위해 생성된 것
  2. 두번째와 세번째는 result.toString()으로 인해 서로 연결되어 있던 employee, dept의 값을 각각 저장하기 위해 실행된 것
  3. ⇒ 이러한 이유는 두 엔티티의 값들에서 fetchType = EAGER로 설정되어 있어서, 바로 값을 가져오기 때문에

3. 여러가지 쿼리 메소드 이름들

/페이지 566 참조

4. 페이징 처리

쿼리 메소드에 Pageable 인터페이스를 추가하면 페이징 기능을 사용할 수 있다

public List<Employee> getEmployeeList(Employee employee, int pageNumber) {
		Pageable paging = PageRequest.of(pageNumber-1, 3);
		return (List<Employee>) empRepository.findByNameContaining(employee.getName(), paging);
	}

Pageable 객체를 사용하여 PageRequest.of 메소드를 사용할 수 있는데 이때 페이지 번호는 0부터 시작하기 때문에 첫 번재 페이지를 보고 싶으면 0부터 시작해야 한다

PageRequest.of(pageNumber-1, 3); ⇒ 첫번째 페이지의 값 3개만 가져와라

결과

Hibernate: 
    select
        employee0_.id as id1_1_,
        employee0_.DEPT_ID as dept_id5_1_,
        employee0_.MAIL_ID as mail_id2_1_,
        employee0_.name as name3_1_,
        employee0_.salary as salary4_1_ 
    from
        S_EMP employee0_ 
    where
        **employee0_.name like ? escape ? limit ?**
Hibernate: 
    select
        department0_.DEPT_ID as dept_id1_0_0_,
        department0_.name as name2_0_0_,
        employeeli1_.DEPT_ID as dept_id5_1_1_,
        employeeli1_.id as id1_1_1_,
        employeeli1_.id as id1_1_2_,
        employeeli1_.DEPT_ID as dept_id5_1_2_,
        employeeli1_.MAIL_ID as mail_id2_1_2_,
        employeeli1_.name as name3_1_2_,
        employeeli1_.salary as salary4_1_2_ 
    from
        S_DEPT department0_ 
    left outer join
        S_EMP employeeli1_ 
            on department0_.DEPT_ID=employeeli1_.DEPT_ID 
    where
        department0_.DEPT_ID=?
직원 목록
--> Employee(id=1, name=개발직원 1, mailId=Dev-1, salary=12700.0)
--> Employee(id=2, name=개발직원 2, mailId=Dev-2, salary=25400.0)
--> Employee(id=3, name=개발직원 3, mailId=Dev-3, salary=38100.0)

limit으로 페이징 처리를 위한 데이터 수를 나누어서 전달하는 것을 볼 수 있다

'BackEnd' 카테고리의 다른 글

[JPA] 영속성 컨텍스트  (0) 2024.08.29
[JPA] Framework  (0) 2024.08.26
[JPA] Spring과 JPA-2  (0) 2024.07.30
[JPA] Spring과 JPA-1  (0) 2024.07.29
[JPA] JPQL 연산자와 함수  (0) 2024.07.25