有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java SpringBoot+JPA为不工作的实体启用二级缓存

我使用Springboot 2.1和spring数据jpa,通过@RepositoryRestResource实现持久化。我已经为我的API调用启用了缓存,这在@Cacheable中运行良好,但现在我想为我的所有JPA实体启用二级缓存,并具有以下配置,但仍然有关于这些实体的任何查询正在触发hibernate查询,而不使用缓存。 请让我知道这个实体缓存缺少什么

渐变依赖性:

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.hibernate.annotations.CacheConcurrencyStrategy;

import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import java.util.Objects;

@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "readOnlyEntityData")
public class Config {

    @Id
    @NotNull
    @Column(unique = true)
    private String code;
    @NotNull
    private String value;
    @NotNull
    @Column(columnDefinition = "boolean default true")
    private boolean status;
    @NotNull
    private String type;

   ......
}

服务类别:

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));
        }
    }
}

J假定:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

@RepositoryRestResource
public interface DBConfigRepository extends JpaRepository<Config, String> {
}

只有标记有@Cacheable响应的方法才会被缓存并工作良好,但是当涉及到数据的实体级缓存时,总是会触发数据库查询来提取数据。请让我知道我错过了什么

编辑:发现只有JPA的findById()从缓存返回,因为hibernate缓存以水合形式存储为键值对,其中id是键。而findAll()findByType()etc方法总是触发数据库查询以获取数据。如何使它们存储并从缓存中返回


共 (0) 个答案