1. 개요

이 짧은 사용방법(예제)에서는 쿼리를 생성할 때 테이블을 조인할 수 있는 Spring Data JPA 사양의 고급 기능에 대해 설명합니다.

JPA 사양 및 사용법에 대한 간략한 요약으로 시작하겠습니다.

2. JPA 사양

Spring Data JPA는 재사용 가능한 컴포넌트로 동적 쿼리를 생성할 수 있도록 하는 사양  인터페이스를 도입했습니다.

이 문서의 코드 예제에서는 AuthorBook 클래스를 사용합니다.

@Entity
public class Author {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstName;

    private String lastName;

    @OneToMany(cascade = CascadeType.ALL)
    private List<Book> books;

    // getters and setters
}

Author 엔터티에 대한 동적 쿼리를 생성하기 위해 사양 인터페이스의 구현을 사용할 수 있습니다.

public class AuthorSpecifications {

    public static Specification<Author> hasFirstNameLike(String name) {
        return (root, query, criteriaBuilder) ->
          criteriaBuilder.like(root.<String>get("firstName"), "%" + name + "%");
    }

    public static Specification<Author> hasLastName(String name) {
        return (root, query, cb) ->
          cb.equal(root.<String>get("lastName"), name);
    }
}

마지막으로 JpaSpecificationExecutor 를 확장 하려면 AuthorRepository 가 필요합니다 .

@Repository
public interface AuthorsRepository extends JpaRepository<Author, Long>, JpaSpecificationExecutor<Author> {
}

결과적으로 이제 두 가지 사양을 함께 연결하고 쿼리를 만들 수 있습니다.

@Test
public void whenFindByLastNameAndFirstNameLike_thenOneAuthorIsReturned() {
    
    Specification<Author> specification = hasLastName("Martin")
      .and(hasFirstNameLike("Robert"));

    List<Author> authors = repository.findAll(specification);

    assertThat(authors).hasSize(1);
}

3. JPA 사양으로 테이블 조인

Author 엔터티가 Book 엔터티 와 일대다 관계를 공유 한다는 데이터 모델을 관찰할 수 있습니다 .

@Entity
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    // getters and setters
}

Criteria Query API를 사용하면 사양 을 생성할 때 두 테이블을 조인할 수 있습니다 . 결과적으로 쿼리 내부에 Book 엔터티의 필드를 포함할 수 있습니다.

public static Specification<Author> hasBookWithTitle(String bookTitle) {
    return (root, query, criteriaBuilder) -> {
        Join<Book, Author> authorsBook = root.join("books");
        return criteriaBuilder.equal(authorsBook.get("title"), bookTitle);
    };
}

이제 이 새 사양을 이전에 만든 사양과 결합해 보겠습니다.

@Test
public void whenSearchingByBookTitleAndAuthorName_thenOneAuthorIsReturned() {

    Specification<Author> specification = hasLastName("Martin")
      .and(hasBookWithTitle("Clean Code"));

    List<Author> authors = repository.findAll(specification);

    assertThat(authors).hasSize(1);
}

마지막으로 생성된 SQL을 살펴보고 JOIN 절을 살펴보겠습니다.

select 
  author0_.id as id1_1_, 
  author0_.first_name as first_na2_1_, 
  author0_.last_name as last_nam3_1_ 
from 
  author author0_ 
  inner join author_books books1_ on author0_.id = books1_.author_id 
  inner join book book2_ on books1_.books_id = book2_.id 
where 
  author0_.last_name = ? 
  and book2_.title = ?

4. 결론

이 기사에서는 JPA 사양을 사용하여 연결된 엔터티 중 하나를 기반으로 테이블을 쿼리하는 방법을 배웠습니다.

Spring Data JPA의 사양은 쿼리를 생성하는 유창하고 동적이고 재사용 가능한 방법으로 이어집니다.

평소와 같이 소스 코드는 GitHub에서 사용할 수 있습니다 .

Persistence footer banner