I'm trying to setup Redisson Hibernate 2L caching but I'm seeing the hibernate query execute every time even though the results are clearly cached on my Redis instance.
When debugging I can see it goes through hibernate and does the query execution and then after it goes into the putIntoCache
from RedissonStorage.java
as expected. When I check Redis I can see the new cached values. However, on a subsequent call to my service it again goes through the hibernate executeQueryStatement
for the the exact same hibernate query but interestingly it then goes into the getFromCache
from RedissonStorage.java
and appears to return the value from Redis. Why is it executing the query every time and not actually checking redis first?
appliation.yml
spring.profiles.active: local
server:
port: 9000
spring:
config:
active:
on-profile: local
cache:
type: redis
jpa:
database: POSTGRESQL
generate-ddl: true
properties:
hibernate:
jdbc:
time_zone: UTC
ddl-auto: create-drop
show_sql: true
cache:
use_query_cache: true
use_second_level_cache: true
factory_class: org.redisson.hibernate.RedissonRegionFactory
redisson:
fallback: true
config: redisson/redisson.yml
datasource:
platform: postgres
url: jdbc:postgresql://localhost:5432/test
username: postgres
password: admin
driverClassName: org.postgresql.Driver
initialization-mode: always
redisson.yml
singleServerConfig:
address: "redis://localhost:6379"
build.gradle
plugins {
id 'org.springframework.boot' version '2.6.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-cache:2.6.4'
implementation 'org.redisson:redisson-hibernate-53:3.16.8'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'org.postgresql:postgresql'
compileOnly 'org.apache.logging.log4j:log4j-api:2.17.1'
compileOnly 'org.apache.logging.log4j:log4j-core:2.17.1'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
Entity class
@Data
@Entity
@Table(name = "employees")
@Cacheable
@Cache(region = "employeeCache", usage = CacheConcurrencyStrategy.READ_WRITE)
public class EmployeeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long employeeId;
private String employeeName;
private String employeeLastName;
}
@Component
public class EmployeeDAO {
@Autowired
private EmployeeRepository employeeRepository;
public EmployeeEntity findByEmployeeId(Long employeeId) {
return employeeRepository.findByEmployeeId(employeeId);
}
@Repository
public interface EmployeeRepository extends CrudRepository<EmployeeEntity, Long> {
EmployeeEntity findByEmployeeId(Long employeeId);
}
CodePudding user response:
Well looks like JPA caching will work for the default findById
but will not work for findAll
or a custom findByType
or in this case findByEmployeeId
.
However, I found a way to make it work by use of @QueryHints
.
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import javax.persistence.QueryHint;
import static org.hibernate.jpa.QueryHints.HINT_CACHEABLE;
@Repository
public interface EmployeeRepository extends CrudRepository<EmployeeEntity, Long> {
@QueryHints(value = { @QueryHint(name = HINT_CACHEABLE, value = "true")})
EmployeeEntity findByEmployeeId(Long employeeId);
}