JPA Repository 는 아주 간단하게 사용할 수 있는 인터페이스입니다.
그러나~ 만약 조건이 길게 늘어진다면??List<Book> findByCategoryIsNullAndNameEqualsAndCreatedAtGreaterThanEqualAndUpdatedAtGreaterThanEqual(String name, LocalDateTime createdAt,LocalDateTime updatedAt);
이런느낌으로! 길어진다면 가독성은 물론 비효율적인 느낌이 듭니다.
TEST에서도@DisplayName("4. QueryTest") @Test void test_4(){ System.out.println("findByCategoryIsNullAndNameEqualsAndCreatedAtGreaterThanEqualAndUpdatedAtGreaterThanEqual : " + bookRepository.findByCategoryIsNullAndNameEqualsAndCreatedAtGreaterThanEqualAndUpdatedAtGreaterThanEqual( "JPA 초격차 패키지", LocalDateTime.now().minusDays(1L), LocalDateTime.now().minusDays(1L) )); }
이렇게 가독성이 너무 떨어집니다.
또, 만약에insert into book(`id`, `name`, `publisher_id`, `created_at`, `updated_at`) values(1, 'JPA 초격자 패키지', 1, false, now(), now()); insert into book(`id`, `name`, `publisher_id`, `created_at`, `updated_at`) values(2, 'Spring', 1, false, now(), now()); insert into book(`id`, `name`, `publisher_id`, `created_at`, `updated_at`) values(3, 'Spring Security', 1, true, now(), now());
위 처럼 쿼리에서
created_at / updated_at 을 매~~~번 넣어줘야 하는 불편함도 있습니다.여기서 아주 센스있게 작성할 수 있게 하는게 Custom Query 입니다.
저번 포스팅중에서 Auditing 참고!
@Data @MappedSuperclass @EntityListeners(value = AuditingEntityListener.class) public class BaseEntity implements Auditable { @CreatedDate @Column(columnDefinition = "datetime(6) default now(6) comment '생성시간'",nullable = false, updatable = false) private LocalDateTime createdAt; @LastModifiedDate @Column(columnDefinition = "datetime(6) default now(6) comment '수정시간'",nullable = false) private LocalDateTime updatedAt; }
@Column 어노테이션으로 쿼리의 기본 설정을 해줄 수 있다.
- nullable = false
- create table 에서 not null 설정
- updatable = false
- 말 그대로 값이 update 되지 않음
- columnDefinition
- "datetime(6) default now(6) comment '생성시간'" 이라고 설정 한다면!
종합하면 이런 식으로 BaseEntity를 상속받은 Entity는 다음과 같은 Table 을 Create 한다.create table author ( id bigint not null auto_increment, created_at datetime(6) default now(6) comment '생성시간' not null, updated_at datetime(6) default now(6) comment '수정시간' not null, country varchar(255), name varchar(255), primary key (id) ) engine=InnoDB
자 ! 봅시다 !
List<Book> findByCategoryIsNullAndNameEqualsAndCreatedAtGreaterThanEqualAndUpdatedAtGreaterThanEqual(String name, LocalDateTime createdAt,LocalDateTime updatedAt);
위 처럼 너무 긴~ 조건을 가진 조건 메소드가 있습니다
이러한 메소드를 Custom Query로 작성한다면
@Query(value = "select b from Book b " +
"where name = :name and createdAt >= :createdAt and updatedAt >= :updatedAt and category is null")
List<Book> findByNameRecently(
@Param("name") String name,
@Param("createdAt")LocalDateTime createdAt,
@Param("updatedAt")LocalDateTime updatedAt);
다음과 같이 작성하게 됩니다.
@Param("컬럼명") 으로 파라미터마다 선언해주고,
@Query(value = "select ~ from ~ where name = :" ) 안에 쿼리문을 작성해주면!
그에 맞는 자리에 들어가 native query가 실행된다.
@Query(value = "select b from Book b " +
"where name = ?1 and createdAt >= ?2 and updatedAt >= ?3 and category is null")
List<Book> findByNameRecently(
String name,
LocalDateTime createdAt,
LocalDateTime updatedAt);
위와 같이 작성해줘도 똑같은 결과를 가져옵니다.