[SPRING] 봄에 시작할 때 @Cache를로드하는 방법?
SPRING봄에 시작할 때 @Cache를로드하는 방법?
나는 봄 캐시를 사용하여 다음과 같이 잘 작동하는 데이터베이스 쿼리를 향상시키고있다.
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("books");
}
@Cacheable("books")
public Book getByIsbn(String isbn) {
return dao.findByIsbn(isbn);
}
하지만 이제 시작할 때 전체 책 캐시를 미리 채워 넣고 싶습니다. 즉, dao.findAll ()을 호출하고 모든 값을 캐시에 저장하려고합니다. 이 루틴은 주기적으로 만 예약되어야합니다.
하지만 @Cacheable을 사용할 때 명시 적으로 캐시를 채울 수 있습니까?
해결법
-
==============================
1.이전과 같이 캐시를 사용하고, 캐시를 업데이트하는 스케줄러를 추가하고, 코드 스 니펫은 아래에 있습니다.
이전과 같이 캐시를 사용하고, 캐시를 업데이트하는 스케줄러를 추가하고, 코드 스 니펫은 아래에 있습니다.
@Service public class CacheScheduler { @Autowired BookDao bookDao; @Autowired CacheManager cacheManager; @PostConstruct public void init() { update(); scheduleUpdateAsync(); } public void update() { for (Book book : bookDao.findAll()) { cacheManager.getCache("books").put(book.getIsbn(), book); } } }
KeyGenerator가 (디폴트로) 하나의 매개 변수에 대한 오브젝트를 리턴하는지 확인하십시오. 그렇지 않으면 cacheManager를 직접 사용하지 않도록 BookService의 putToCache 메소드를 노출하십시오.
@CachePut(value = "books", key = "#book.isbn") public Book putToCache(Book book) { return book; }
-
==============================
2.시작할 때 메모리의 모든 인스턴스가 필요하다면 직접 버퍼에 저장해야합니다. findAll () 메소드를 사용하여 캐시에 넣으면 findAll ()에 @Cacheable 주석을 추가해야합니다. 그런 다음 시작할 때 findAll ()을 호출해야합니다. 그러나 findAll ()을 호출 할 때 해당 인스턴스가 캐시에 저장되어 있어도 getByIsbn (String isbn)을 호출하면 캐시에 액세스한다는 것을 의미하지는 않습니다. 실제로는 ehcache가 메서드 반환 값을 메서드가 호출 될 때 key가 계산되는 키 / 값 쌍으로 캐시하기 때문에 그렇지 않습니다. 따라서 반환 된 유형이 동일하지 않으며 키가 모든 인스턴스에 대해 절대 일치하지 않으므로 findAll ()의 반환 값과 getByIsbn (String)의 반환 값을 일치시키는 방법을 알 수 없습니다.
시작할 때 메모리의 모든 인스턴스가 필요하다면 직접 버퍼에 저장해야합니다. findAll () 메소드를 사용하여 캐시에 넣으면 findAll ()에 @Cacheable 주석을 추가해야합니다. 그런 다음 시작할 때 findAll ()을 호출해야합니다. 그러나 findAll ()을 호출 할 때 해당 인스턴스가 캐시에 저장되어 있어도 getByIsbn (String isbn)을 호출하면 캐시에 액세스한다는 것을 의미하지는 않습니다. 실제로는 ehcache가 메서드 반환 값을 메서드가 호출 될 때 key가 계산되는 키 / 값 쌍으로 캐시하기 때문에 그렇지 않습니다. 따라서 반환 된 유형이 동일하지 않으며 키가 모든 인스턴스에 대해 절대 일치하지 않으므로 findAll ()의 반환 값과 getByIsbn (String)의 반환 값을 일치시키는 방법을 알 수 없습니다.
-
==============================
3.옵션은 CommandLineRunner를 사용하여 시작할 때 캐시를 채우는 것입니다.
옵션은 CommandLineRunner를 사용하여 시작할 때 캐시를 채우는 것입니다.
공식 CommandLineRunner 문서에서 볼 수있는 것은 다음과 같습니다.
따라서 사용 가능한 모든 책 목록을 검색 한 다음 CacheManager를 사용하여 책 캐시를 채 웁니다.
@Component public class ApplicationRunner implements CommandLineRunner { @Autowired private BookDao dao; @Autowired private CacheManager cacheManager; @Bean public CacheManager cacheManager() { return new ConcurrentMapCacheManager("books"); } @Override public void run(String... args) throws Exception { List<Book> results = dao.findAll(); results.forEach(book -> cacheManager.getCache("books").put(book.getId(), book)); } }
-
==============================
4.올리비에 (Olivier)가 지정했듯이, 스프링 캐시가 단일 객체로 함수를 출력하기 때문에 findAll로 @cacheable 표기법을 사용하면 나중에 개별적으로 액세스 할 수 있도록 캐시의 모든 객체를로드 할 수 없습니다.
올리비에 (Olivier)가 지정했듯이, 스프링 캐시가 단일 객체로 함수를 출력하기 때문에 findAll로 @cacheable 표기법을 사용하면 나중에 개별적으로 액세스 할 수 있도록 캐시의 모든 객체를로드 할 수 없습니다.
캐시에있는 모든 오브젝트를로드 할 수있는 한 가지 방법은 사용중인 캐시 솔루션이 시작시 모든 오브젝트를로드하는 방법을 제공하는지 여부입니다. 예를 들어 NCache / TayzGrid와 같은 솔루션은 구성 가능한 캐시 시작 로더를 사용하여 개체를 시작할 때 캐시를로드 할 수있는 캐시 시작 로더 기능을 제공합니다.
-
==============================
5.@PostConstruct를 사용할 때 다음과 같은 문제가 발생했습니다. - 비록 캐시 된 메서드를 호출했지만 swagger에서 호출 한 후에도 여전히 캐시 된 값을 사용하지 않았습니다. 한 번 더 전화 한 후에.
@PostConstruct를 사용할 때 다음과 같은 문제가 발생했습니다. - 비록 캐시 된 메서드를 호출했지만 swagger에서 호출 한 후에도 여전히 캐시 된 값을 사용하지 않았습니다. 한 번 더 전화 한 후에.
왜냐하면 @PostConstruct가 너무 빨라서 뭔가를 캐싱하기 때문입니다. (적어도 나는 그것이 문제라고 생각한다)
이제는 시동 과정에서 더 늦게 사용하고 있으며 문제없이 작동합니다.
@Component public class CacheInit implements ApplicationListener<ApplicationReadyEvent> { @Override public void onApplicationEvent(ApplicationReadyEvent event) { //call service method } }
-
==============================
6.다른 빈 BookCacheInitialzer를 추가하십시오.
다른 빈 BookCacheInitialzer를 추가하십시오.
BookCacheInitialzer에서 현재 Bean BookService를 자동 와이어 링합니다.
BookCacheInitialzer의 PostConstruct 메소드에서 의사 코드
다음과 같이 할 수 있습니다.
class BookService { @Cacheable("books") public Book getByIsbn(String isbn) { return dao.findByIsbn(isbn); } public List<Book> books; @Cacheable("books") public Book getByIsbnFromExistngBooks(String isbn) { return searchBook(isbn, books); }
}
class BookCacheInitialzer { @Autowired BookService service @PostConstruct public void initialize() { books = dao.findAll(); service.books = books; for(Book book:books) { service.getByIsbnFromExistngBooks(book.getIsbn()); } }
}
from https://stackoverflow.com/questions/27940704/how-to-load-cache-on-startup-in-spring by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 복합 ID가있는 엔티티에 대한 HATEOAS 링크 생성 사용자 정의 (0) | 2019.01.02 |
---|---|
[SPRING] 스프링 데이터 (JPA) 저장소를 계측 / 조언하는 방법은 무엇입니까? (0) | 2019.01.02 |
[SPRING] 스프링 MVC 스프링 보안과 에러 처리 (0) | 2019.01.02 |
[SPRING] convertAndSendToUser에서 "user"가 나오는 곳은 SockJS + Spring Websocket에서 작동합니까? (0) | 2019.01.02 |
[SPRING] Spring MessageSource는 다중 클래스 경로를 지원합니까? (0) | 2019.01.02 |