Jpa Repository 커스텀
JPA를 처음 접했을 때 느낀 의문점은 어떻게 이걸로 복잡한 쿼리를 작성할 수 있을까? 라는 것이었다. 위 문서는 이 의문에 대한 해답을 제시해주는 문서이다.
요약하자면 내용은 이렇다.
리포지토리에 상단 문서에 맞는 양식으로 메소드를 선언해주면 알아서 그 로직을 구성해준다.
자바답지 않게 친절한척하는데 조금 불친절하면서 그 형식이 충격적이다. 메소드명으로 어떻게 기능을 구분지어 구현시킬 생각을 했는지 참 창의적이다.
간단하게 내가 작성해본 것을 예시로 설명해보겠다.
public interface BoardRepository extends JpaRepository<Board, Long> {
List<Board> findAllByOrderByModifiedAtDesc();
}
SQL로 치자면
SELECT *
FROM BOARD
ORDER BY ModifiedAt DESC;
이정도 되지 않을까. SQL 안 쓴지 2년이 넘어서 문법이 맞는진 모르겠다.
정말 신기한 점은 내가 선언했던 Entity의 Column 요소도 이름에 가져다 쓸 수 있다는 점이다.
사용상의 주의사항으로는, 구문을 어떻게 구성하는가에 따라 매개변수도 입력받을 수 있으니 참고하자. 자세한건 상단의 사이트에서 확인해보면 되겠다.
Scheduler
- 정해진 주기로 특정 메소드를 반복시킬 수 있는 기능
@RequiredArgsConstructor // final 멤버 변수를 자동으로 생성합니다.
@Component // 스프링이 필요 시 자동으로 생성하는 클래스 목록에 추가합니다.
public class Scheduler {
private final ProductRepository productRepository;
private final ProductService productService;
private final NaverShopSearch naverShopSearch;
// 초, 분, 시, 일, 월, 주 순서
@Scheduled(cron = "0 0 1 * * *")
public void updatePrice() throws InterruptedException {
System.out.println("가격 업데이트 실행");
// 저장된 모든 관심상품을 조회합니다.
List<Product> productList = productRepository.findAll();
for (int i=0; i<productList.size(); i++) {
// 1초에 한 상품 씩 조회합니다 (Naver 제한)
TimeUnit.SECONDS.sleep(1);
// i 번째 관심 상품을 꺼냅니다.
Product p = productList.get(i);
// i 번째 관심 상품의 제목으로 검색을 실행합니다.
String title = p.getTitle();
String resultString = naverShopSearch.search(title);
// i 번째 관심 상품의 검색 결과 목록 중에서 첫 번째 결과를 꺼냅니다.
List<ItemDto> itemDtoList = naverShopSearch.fromJsonToItems(resultString);
ItemDto itemDto = itemDtoList.get(0);
// i 번째 관심 상품 정보를 업데이트합니다.
Long id = p.getId();
productService.updateBySearch(id, itemDto);
}
}
}
@EnableScheduling // 스프링 부트에서 스케줄러가 작동하게 합니다.
@EnableJpaAuditing // 시간 자동 변경이 가능하도록 합니다.
@SpringBootApplication // 스프링 부트임을 선언합니다.
public class Week04Application {
public static void main(String[] args) {
SpringApplication.run(Week04Application.class, args);
}
}
네이버 쇼핑 API를 이용해 만든 Scheduler 예시다.
내가 등록해놓은 관심상품의 최저가를 특정 시간마다 갱신해주는 것이다. 위의 예시는 매일 01시에 갱신해주도록 되어있다.
만드는 순서는 다음과 같다.
1. 스프링 어플리케이션 클래스에 @EnableScheduling 어노테이션 선언
2. Scheduler가 되어줄 클래스에 @Component(Bean 인스턴스 생성) 어노테이션 선언
3. 대상 메소드에 @Scheduled(cron = "초 분 시 일 월 주") 어노테이션 선언. * 사용시 와일드카드 적용.
4. 메소드 구현
좀 복잡해보인다고 생각했는데, 정리해보니 그냥 어노테이션만 해주면 구현을 제외한 모든 작업은 스프링이 해준다. 엄청 간편하다.
Bean
- 사용자가 직접 생성한 인스턴스가 아닌, Spring IoC 컨테이너가 관리해주는 객체들을 의미한다.
위 사이트에서 정리를 알차게 해 두어서 위 내용을 보고 Bean으로 등록하는 방법을 간략하게 정리해보겠다.
1. @Component 어노테이션 사용
-> @SpringBootApplication 어노테이션 내부에는 @ComponentScan 어노테이션이 정의되어 있는데, 이 어노테이션은 하위 클래스를 돌면서 @Component를 찾는 역할을 수행한다. 이후 확인된 Components는 Bean에 등록이 된다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
실제로 SpringBootApplication 내부는 위처럼 @ComponentScan이 선언되어있음을 알 수 있다.
2. Bean 설정파일에 직접 등록
-> @Component 어노테이션을 사용하는 어노테이션인 @Configuration을 이용해 직접 등록해줄 수 있다.
@Configuration
public class SampleConfiguration {
@Bean
public SampleController sampleController() {
return new SampleController;
}
}
1.은 클래스 단위, 2.는 메소드 단위에서 등록한다는데, 둘의 차이점은 직접 구분해서 써야하는 상황을 맞이해봐야 알 것 같다.....
'기술 > Spring-Boot' 카테고리의 다른 글
Controller는 뭘 하는 녀석일까? (0) | 2021.11.26 |
---|---|
@RequestBody는 왜 Setter가 없어도 작동할까? (0) | 2021.11.24 |
항해99 11/19(금) 스프링 TIL (0) | 2021.11.19 |
항해99 11/18(목) 스프링 TIL (0) | 2021.11.18 |
항해99 11/15(월) 스프링 TIL (0) | 2021.11.15 |
댓글