[Book Study] 스프링 부트 핵심 가이드
8. Spring Data JPA 활용
8 - 1 . 쿼리 메서드
쿼리 메서드의 생성
- 크게 동작을 결정하는 주제와 서술어로 구분
- 'find...By', 'exists...By'와 같은 키워드로 쿼리의 주제 정함
- 'By'는 서술어의 시작을 나타내는 구분자의 역할
리포지토리의 쿼리의 구조
리턴타입 + {주제 + 서술어(속성)}
ex)
쿼리 메서드의 주제 키워드
- find...By
- read...By
- get...By
- query...By
- search...By
- stream...By
리턴타입으로 Collection이나 Stream에 속한 하위 타입을 설정 가능
exists...By
- 특정 데이터가 존재하는지 확인하는 키워드, 리턴 타입으로는 boolean 타입을 사용
count...By
- 조회 쿼리를 수행한 후 쿼리 결과로 나온 레코드의 개수를 리턴
delete...By, remove...By
- 삭제 쿼리를 수행
- 리턴타입이 없거나 삭제한 횟수를 리턴
void deleteByName(String name);
long removeByName(String name);
First<number>, Top<number>
- 쿼리를 통해 조회된 결괏값의 개수를 제한하는 키워드
List<ClassExample> findFirst5ByName(String name);
List<ClassExmple> findTop10ByName(String name);
8 - 2. 조건자 키워드
Is
- 값의 일치를 조건으로 사용하는 키워드
ClassExample findByNumberIs(Long number);
ClassExample findByNameEquals(String name);
Not
- 값의 불일치를 조건으로 사용하는 키워드
ClassExample findByNameIsNot(String name);
ClassExample findByNumberNot(Long number);
Null, NotNull
- null인지 검사하는 키워드
List<ClassExample> findByCountryNull();
List<ClassExample> findByCountryIsNull();
List<ClassExample> findByPetNotNull();
List<ClassExample> findByPetIsNotNull();
True, False
- boolean타입으로 지정된 칼럼값을 확인하는 키워드
ClassExample findByCheckedTrue();
ClassExample findByCheckedIsTrue();
ClassExample findByCheckedFalse();
ClassExample findByCheckedIsFalse();
And, Or
- 여러 조건을 묶을 때 사용
ClassExample findByNameAndCountry(String name, String country);
ClassExample findByNameOrCountry(String name, String country);
GreaterThan, LessThan, Between
- 숫자나 datetime 칼럼을 대상으로 한 비교 연산에 사용할 수 있는 키워드
List<ClassName> findByAgeGreaterThan(Long age);
List<ClassName> findByAgeIsGreaterThan(Long age);
List<ClassName> findByAgeIsGreaterThanEqual(Long age);
List<ClassName> findByAgeIsLessThan(Long age);
List<ClassName> findByAgeLessThan(Long age);
List<ClassName> findByAgeLessThanEqual(Long age);
List<ClassName> findByAgeIsBetween(Long age1, Long age2);
List<ClassName> findByAgeBetween(Long age1, Long age2);
StartingWith, EndingWith, Containing, Like
- 칼럼값에서 일부 일치 여부를 확인하는 키워드
- SQL쿼리문에서 값의 일부를 포함하는 값을 추출할 때 사용하는 '%'키워드와 동일한 역할
List<ClassName> findByNameLike(String name);
List<ClassName> findByNameIsLike(String name);
List<ClassName> findByCountryContains(String country);
List<ClassName> findByCountryContaining(String country);
List<ClassName> findByCountryIsContaining(String country);
List<ClassName> findByCompanyStartsWith(String company);
List<ClassName> findByCompanyStartingWith(String company);
List<ClassName> findByCompayIsStartingWith(String company);
List<ClassName> findByUserNameEndsWith(String userName);
List<ClassName> findByUserNameEndingWith(String userName);
List<ClassName> findByUserNameIsEndingWith(String userName);
8 - 3 . 정렬과 페이징 처리
정렬처리하기
OrderBy
- 기본 쿼리를 작성한 후 정렬하고자 하는 칼럼과 오름, 내림차순을 설정하면 정렬이 수행된다.
- And나 Or을 사용하지 않고, 우선순위를 기준으로 차례대로 작성하면 된다.
가독성 문제의 해결
쿼리 메서드의 이름에 정렬 키워드를 삽입해서 정렬하는 것도 가능하지만 가독성이 떨어지는 문제
이를 해결하기 위해 매개변수를 활용해 정렬
페이징 처리
페이징이란 데이터베이스의 레코드를 개수로 나눠 페이지로 구분하는 것을 의미
JPA에서는 이같은 페이징 처리를 위해 Page와 Pageable을 사용
// PlayerRepository
Page<Player> findByName(String name, Pageable pageable);
// PlayerRepositoryTest
PlayerRepository playerRepository;
Page<Player> playerPage = playerRepository.findByName("Alex", pageRequest.of(0,2));
System.out.println(playerPage.getContent());
PageRequest는 Pageable의 구현체
일반적으로 PageRequest는 of메서드를 통해 PageRequest 객체를 생성
of 메서드는 매개변수에 따라 다양한 형태로 오버로딩\
8 - 4 . @Query 어노테이션 활용하기
- 데이터베이스에서 값을 가져올때 쿼리메서드를 생성할수도 있고, Query 어노테이션을 사용해 직접 JPQL을 작성 가능
@Query("SELECT * FROM Players WHERE Players.name=?1")
List<Players> findByName(String name);
QueryDSL
- 정적 타입을 이용해 SQL과 같은 쿼리를 생성할 수 있도록 지원하는 프레임워크
- 문자열이나 XML파일을 통해 쿼리를 작성하는 대신 QueryDSL이 제공하는 플루언티 API를 활용해 쿼리를 생성할 수 있다.
장점
- IDE가 제공하는 코드 자동완성 기능을 사용
- 문법적으로 잘못된 쿼리를 허용하지 않음 -> 정상적으로 활용된 QueryDSL은 문법 오류를 발생시키지 않음
- 고정된 SQL 쿼리를 작성하지 않기 때문에 동적으로 쿼리를 생성 가능
- 코드로 작성하므로 가독성 및 생산성이 향상
- 도메인 타입과 프로퍼티를 안전하게 참조
8 - 5 . JPA Auditing
많이 사용되는 필드
- 생성 주체
- 생성 일자
- 변경 주체
- 변경 일자
// Configuration.java
@Configuration
@EnableJpaAuditing
public class ProjectJpaAuditingConfiguration{
}
// ProjectApplication.java
@SpringBootApplication
public class ProjectApplication{
public static void main(String[] args) {
SpringApplication.run(PApplication.class, args);
}
}
BaseEntity 생성
-중복 코드를 없애기 위해 각 엔티티에 공통으로 들어가게 되는 칼럼(필드)를 하나의 클래스로 빼는 작업을 수행
// BaseEntity.java
@Getter
@Setter
@ToString
@MappedSuperClass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
}
@MappedSuperClass
- JPA의 엔티티 클래스가 상속받을 경우 자식 클래스에게 매핑 정보를 전달
@EntityListeners
- 엔티티를 데이터베이스에 적용하기 전후로 콜백을 요청할 수 있게 하는 어노테이션
AuditingEntityListener
- 엔티티의 Auditing 정보를 주입하는 JPA 엔티티 리스너 클래스
@CreatedDate
- 데이터 생성 날짜를 자동으로 주입하는 어노테이션
@LastModifiedDate
- 데이터 수정 날짜를 자동으로 주입하는 어노테이션
// Domain.java
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString(callSuper = true)
@Table(name = "domain")
public class Domain extends BaseEntity {
@Id
@GenerateValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Long age;
@Column(nullable = false)
private Long number;
}
'Web Develop > Book Study' 카테고리의 다른 글
[Book Study] 스프링 부트 핵심 가이드 - 10. 유효성 검사와 예외 처리 (0) | 2023.09.25 |
---|---|
[Book Study] 스프링 부트 핵심 가이드 - 9. 연관관계 매핑 (0) | 2023.09.25 |
[Book Study] 스프링 부트 핵심 가이드 - 6. 데이터베이스 연동 (0) | 2023.09.09 |
[Book Study] 스프링 부트 핵심 가이드 - 5. API를 작성하는 다양한 방법 (3) | 2023.08.30 |
[Book Study] 스프링 부트 핵심 가이드 - 4. 스프링 부트 애플리케이션 개발하기 (0) | 2023.08.30 |
댓글