Java SpringBoot&x2B;JPA为不工作的实体启用二级缓存
我使用Springboot 2.1和spring数据jpa,通过@RepositoryRestResource实现持久化。我已经为我的API调用启用了缓存,这在@Cacheable中运行良好,但现在我想为我的所有JPA实体启用二级缓存,并具有以下配置,但仍然有关于这些实体的任何查询正在触发hibernate查询,而不使用缓存。 请让我知道这个实体缓存缺少什么 渐变依赖性:Java SpringBoot&x2B;JPA为不工作的实体启用二级缓存,java,spring-boot,jpa,second-level-cache,ehcache-3,Java,Spring Boot,Jpa,Second Level Cache,Ehcache 3,我使用Springboot 2.1和spring数据jpa,通过@RepositoryRestResource实现持久化。我已经为我的API调用启用了缓存,这在@Cacheable中运行良好,但现在我想为我的所有JPA实体启用二级缓存,并具有以下配置,但仍然有关于这些实体的任何查询正在触发hibernate查询,而不使用缓存。 请让我知道这个实体缓存缺少什么 渐变依赖性: dependencies { implementation 'org.springframework.boot:spring
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
implementation 'org.springframework.boot:spring-boot-starter-hateoas'
implementation 'org.springframework.boot:spring-boot-starter-jersey'
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'org.ehcache:ehcache:3.7.1'
implementation 'javax.cache:cache-api'
compile group: 'org.hibernate', name: 'hibernate-jcache', version: '5.3.10.Final'
runtimeOnly 'mysql:mysql-connector-java'
}
应用程序属性
spring.datasource.url=jdbc:mysql://localhost:3306/mar_db
spring.datasource.username=root
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.MySQL57Dialect
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.jcache.JCacheRegionFactory
spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE
spring.cache.jcache.config=classpath:ehcache.xml
ehcache.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ehcache.org/v3"
xmlns:jsr107="http://www.ehcache.org/v3/jsr107">
<service>
<jsr107:defaults enable-statistics="true" />
</service>
<cache alias="readOnlyEntityData">
<key-type>java.lang.Object</key-type>
<expiry>
<ttl unit="minutes">360</ttl>
</expiry>
<listeners>
<listener>
<class>com.tfsc.ilabs.selfservice.common.utils.CacheLogger</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>UNORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>UPDATED</events-to-fire-on>
<events-to-fire-on>EXPIRED</events-to-fire-on>
<events-to-fire-on>REMOVED</events-to-fire-on>
<events-to-fire-on>EVICTED</events-to-fire-on>
</listener>
</listeners>
<resources>
<heap unit="entries">1000</heap>
<offheap unit="MB">256</offheap>
</resources>
</cache>
</config>
服务类别:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
public class DBConfigServiceImpl implements DBConfigService {
@Autowired
private DBConfigRepository dbConfigRepository;
@Override
public List<ConfigDTO> findAll() {
return dbConfigRepository.findAll().stream().map(Config::toDTO).collect(Collectors.toList());
}
@Cacheable(value = "readOnlyEntityData", keyGenerator = "cacheKeyGenerator")
@Override
public ConfigDTO findByCode(String code) {
Optional<Config> config = dbConfigRepository.findById(code);
if(config.isPresent()){
return config.get().toDTO();
}else {
throw new NoSuchResourceException(new ErrorObject("Config not found {0}", code));
}
}
}
import org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.cache.annotation.Cacheable;
导入org.springframework.stereotype.Service;
导入java.util.List;
导入java.util.Optional;
导入java.util.stream.collector;
@服务
公共类DBConfigServiceImpl实现DBConfigService{
@自动连线
专用DBConfigRepository DBConfigRepository;
@凌驾
公共列表findAll(){
返回dbConfigRepository.findAll().stream().map(Config::toDTO).collect(Collectors.toList());
}
@可缓存(value=“readOnlyEntityData”,keyGenerator=“cacheKeyGenerator”)
@凌驾
公共配置为findByCode(字符串代码){
可选配置=dbConfigRepository.findById(代码);
if(config.isPresent()){
返回config.get().toDTO();
}否则{
抛出新的NoSuchResourceException(新的ErrorObject(“未找到配置{0}”,代码));
}
}
}
J假定:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
@RepositoryRestResource
public interface DBConfigRepository extends JpaRepository<Config, String> {
}
import org.springframework.data.jpa.repository.JpaRepository;
导入org.springframework.data.rest.core.annotation.RepositoryRestResource;
@存储资源
公共接口DBConfigRepository扩展了JpaRepository{
}
只有标记有@Cacheable响应的方法才会被缓存并工作良好,但是当涉及到数据的实体级缓存时,总是会触发数据库查询来提取数据。请让我知道我错过了什么
编辑:发现只有JPA的findById()从缓存返回,因为hibernate缓存以水合形式存储为键值对,其中id是键。而findAll()和findByType()etc方法总是触发数据库查询以获取数据。如何使它们存储并从缓存中返回 您是否需要将
findAll()
,findByType()
(您想要使用二级缓存的任何其他方法)方法添加到DBConfigRepository
,并使用@QueryHints(value={@QueryHint(name=org.hibernate.jpa.QueryHints.HINT\u CACHEABLE,value=“true”)}注释它们
(因为此注释无法应用于整个存储库)?@iVetal感谢添加查询点后,它开始缓存查询。知道它将如何过期并从缓存中删除吗?以及如何控制,因为这些查询点不受我声明的ehcache.xml控制。
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
@RepositoryRestResource
public interface DBConfigRepository extends JpaRepository<Config, String> {
}