쿼리 캐시를 사용하지 않고 Spring Data JPA 쿼리 방식의 결과를 캐시하려면 어떻게 해야 합니까?
Spring Data JPA(하이버네이트 백엔드) 저장소 클래스가 있는 Spring Boot 앱을 가지고 있습니다.몇 가지 커스텀 파인더 메서드를 추가했습니다.또, 특정의 Finder 메서드에는@Query
주석을 사용하여 데이터를 가져오는 방법을 설명합니다.하이버네이션 2레벨 캐시용으로 이미 EhCache를 설정했습니다만, 지금까지 이러한 결과를 캐싱할 수 있는 유일한 방법은 하이버네이션 쿼리 캐시를 유효하게 하는 것입니다.특정 캐시를 정의하고 실제 도메인 개체를 일반 검색기처럼 저장합니다.다음은 제 보고서 코드입니다.
public interface PromotionServiceXrefRepository extends PagingAndSortingRepository<PromotionServiceXref, Integer> {
@Query("SELECT psx FROM Customer c " +
"JOIN c.customerProductPromotions cpp " +
"JOIN cpp.productPromotion pp " +
"JOIN pp.promotion p JOIN p.promotionServiceXrefs psx " +
"WHERE c.customerId = ?1")
@QueryHints(@QueryHint(name = "org.hibernate.cacheable", value = "true"))
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "promotionServiceXrefByCustomerId")
Set<PromotionServiceXref> findByCustomerId(int customerId);
}
정의되어 있는 "promission Service Xref By CustomerId" 캐시는 사용되지 않습니다.
<cache name="promotionServiceXrefByCustomerId" overflowToDisk="true" diskPersistent="true"
maxEntriesLocalHeap="3000000" eternal="true" diskSpoolBufferSizeMB="20" memoryStoreEvictionPolicy="LFU"
transactionalMode="off" statistics="true">
</cache>
내가 뭘 잘못하고 있지?유효하게 하면StandardQueryCache
이 데이터는 캐시에 저장되고 휴지 상태에서는 쿼리는 실행되지 않습니다.단, 쿼리 캐시를 비활성화하면 이 캐시는 캐시되지 않습니다.내가 여기서 뭘 잘못하고 있는 거지?도와주세요!
당신이 가지고 있는 코드가 작동하지 않는 이유는@Cache
그런 식으로 작동하도록 의도된 것이 아닙니다.쿼리 메서드 실행 결과를 캐시하려면 Spring의 캐시 추상화를 사용하는 것이 가장 쉬운 방법입니다.
interface PromotionServiceXrefRepository extends PagingAndSortingRepository<PromotionServiceXref, Integer> {
@Query("…")
@Cacheable("servicesByCustomerId")
Set<PromotionServiceXref> findByCustomerId(int customerId);
@Override
@CacheEvict(value = "servicesByCustomerId", key = "#p0.customer.id")
<S extends PromotionServiceXref> S save(S service);
}
이 설정에 의해, 다음의 콜의 결과가 발생합니다.findByCustomerId(…)
고객 ID에 의해 캐시됩니다.주의해 주세요.@CacheEvict
무시당해서save(…)
쿼리 방식으로 채운 캐시가 엔티티가 저장될 때마다 제거되도록 합니다.이것은 아마도 에 전파되어야 합니다.delete(…)
메서드도 있습니다.
이제 전용 설정을 진행할 수 있습니다.CacheManager
(자세한 내용은 참조 문서 참조) 원하는 캐싱 솔루션을 플러그 인합니다(플레인 사용).ConcurrentHashMap
여기)를 참조해 주세요.
@Configuration
@EnableCaching
class CachingConfig {
@Bean
CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.addCaches(Arrays.asList(new ConcurrentMapCache("servicesByCustomerId)));
return cacheManager;
}
}
휴지 상태 QueryCache를 포기함으로써 저장, 업데이트, 업데이트 시 오래된 쿼리를 무효화할 책임이 있음을 유의해야 합니다.쿼리 결과에 영향을 준 엔티티 삭제(CacheEvict를 저장으로 설정함으로써 Oliver가 하고 있는 작업)는 귀찮을 수 있습니다.또, 시나리오에 문제가 되지 않는 경우는, 적어도 그것을 고려해 무시할 필요가 있습니다.
먼저 질문을 인용하겠습니다.
내가 뭘 잘못하고 있지?
캐시에 이름을 붙이는 방법이 휴지 상태의 캐시를 사용하는 방법에 적합하지 않습니다.확인.org.hibernate.engine.spi.CacheInitiator
명령어는 ""를 사용합니다.org.hibernate.internal.CacheImpl
이 되다
if ( settings.isQueryCacheEnabled() ) {
final TimestampsRegion timestampsRegion = regionFactory.buildTimestampsRegion(
qualifyRegionName( UpdateTimestampsCache.REGION_NAME ),
sessionFactory.getProperties()
);
updateTimestampsCache = new UpdateTimestampsCache( sessionFactory, timestampsRegion );
...
}
★★★★★★★★★★★★★★★★★.UpdateTimestampsCache.REGION_NAME
: (예:)에)org.hibernate.cache.spi.UpdateTimestampsCache
)는 캐시명으로 입력되지 않은 이름입니다.쿼리 캐시에는 다른 캐시 이름 없이 해당 캐시 이름을 사용해야 합니다.
이제 문제와 관련된 다른 생각은 거의 없습니다.
- , 의
@Cache
을 「」로 합니다.org.hibernate.cache.spi.UpdateTimestampsCache
최대 절전 모드에 의해 쿼리를 ehcache로 캐시할 수 있습니다(여기에는 스프링 캐시 추상화가 포함되지 않습니다). - 하드코드된 캐시 이름을 설정하는 것은 당신을 행복하게 하지 않을 것입니다.확실하지만 적어도 당신은 왜 이런 일이 일어나는지 알고 있습니다.
- Balamaci Serban(아래 게시물)은 고통스러울 정도로 옳다.
다음은 ehcache + @Query + @QueryHints가 예상대로 동작하는 프로젝트 중 하나에서의 설정입니다.ehcache/ehcache-in-memory.xml
삭제):
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="in-memory" xmlns="http://ehcache.org/ehcache.xsd">
<!--<diskStore path="java.io.tmpdir"/>-->
<!--
30d = 3600×24×30 = 2592000
-->
<cache name="org.hibernate.cache.internal.StandardQueryCache"
maxElementsInMemory="9999" eternal="false"
timeToIdleSeconds="2592000" timeToLiveSeconds="2592000"
overflowToDisk="false" overflowToOffHeap="false"/>
<cache name="org.hibernate.cache.spi.UpdateTimestampsCache"
maxElementsInMemory="9999" eternal="true"
overflowToDisk="false" overflowToOffHeap="false"/>
<defaultCache maxElementsInMemory="9999" eternal="false"
timeToIdleSeconds="2592000" timeToLiveSeconds="2592000"
overflowToDisk="false" overflowToOffHeap="false"/>
</ehcache>
및 hibernate.properties:
hibernate.jdbc.batch_size=20
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.validator.autoregister_listeners=false
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
hibernate.hbm2ddl.auto=update
net.sf.ehcache.configurationResourceName=ehcache/ehcache-in-memory.xml
hibernate.dialect=org.hibernate.dialect.H2Dialect
pom.xml의 일부 버전은 다음과 같습니다.
<springframework.version>5.0.6.RELEASE</springframework.version>
<spring-security.version>5.0.5.RELEASE</spring-security.version>
<spring-data-jpa.version>2.1.0.RELEASE</spring-data-jpa.version>
<hibernate.version>5.2.13.Final</hibernate.version>
<jackson-datatype-hibernate5.version>2.9.4</jackson-datatype-hibernate5.version>
그리고 완전한 테스트는 이미지입니다.persistency.stratory.ImageRepositoryTest.java는 다음 URL에서 찾을 수 있습니다.https://github.com/adrhc/photos-server/tree/how-to-cache-results-of-a-spring-data-jpa-query-method-without-using-query-cache
뛰어요, 뛰어!mvn clean install
나의 ★★★★★★★★★★★★★★★★★★★★★★env.sh
내 셸 스크립트를 정말로 사용하고 싶다면.합니다.imageRepository.count()
discl.discl.discl을 클릭합니다.
언급URL : https://stackoverflow.com/questions/26242492/how-to-cache-results-of-a-spring-data-jpa-query-method-without-using-query-cache
'source' 카테고리의 다른 글
JavaScript를 사용하여 서버에서 텍스트 파일을 읽는 방법 (0) | 2023.04.01 |
---|---|
숍 페이지만을 대상으로 합니다. (0) | 2023.04.01 |
ui-sref와 $state.go의 각도 차이JS UI 라우터 (0) | 2023.03.27 |
한 프로젝트의 spring-config.xml을 다른 프로젝트의 spring-config.xml로 Import하려면 어떻게 해야 합니까? (0) | 2023.03.27 |
$scope의 차이는 무엇입니까?$root 및 $rootScope? (0) | 2023.03.27 |