我想重新创建的案例:
构建.gradle:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.hibernate.orm:hibernate-jcache:6.1.6.Final'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.ehcache:ehcache:3.10.8'
}
应用程序属性:
spring.jpa.show-sql=true
spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.generate_statistics=true
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=
org.hibernate.cache.jcache.JCacheRegionFactory
spring.jpa.hibernate.ddl-auto=none
缓存初始化:
@Configuration
public class CacheConfig {
private final RegionsRepo repo;
public CacheConfig(RegionsRepo repo) {
this.repo = repo;
}
@PostConstruct
public void initCache() {
repo.findAll().forEach(region -> {});
}
}
实体注释:
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Table(name = "regions")
和 JpaRepository:
public interface RegionsRepo extends JpaRepository<Regions, Long> {
Optional<Regions> findRegionsByExternalid(Integer id);
@Override
Optional<Regions> findById(Long aLong);
@Override
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<Regions> findAll();
}
启动应用程序后,将表放入二级休眠缓存中。日志:
346333 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
73250 nanoseconds spent preparing 1 JDBC statements;
1098084 nanoseconds spent executing 1 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
5962251 nanoseconds spent performing 3 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
368667 nanoseconds spent performing 1 L2C misses;
0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
68458 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
当我调用存储库方法时
按 ID 查找
这是从 JpaRepository 重写的,我看到没有执行 JDBC 语句,只是纯粹的 L2C 命中,这正是我所需要的。 日志:
1277291 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
0 nanoseconds spent preparing 0 JDBC statements;
0 nanoseconds spent executing 0 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
418709 nanoseconds spent performing 1 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
但是当我使用自定义的而不是重写的方法时
通过外部 ID 查找区域
L2C 命中被忽略。日志:
742083 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
849083 nanoseconds spent preparing 1 JDBC statements;
2029042 nanoseconds spent executing 1 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
670583 nanoseconds spent performing 1 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
您能告诉一下这种情况下 hibernate 缓存配置有什么问题吗?
我应该怎么做才能让 hibernate 在非重写的 JpaRepository 方法中使用 L2C 缓存?
最终自己解决了。
由于 hibernate-jache 默认提供程序可以通过作为主键的实体 id 进行搜索,因此我只是在数据库中重新创建没有 id 的实体。
之前签名:
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
Integer externalid;
String externalname;
Integer internalid;
String internalname;
这里我们只需使用Long id字段就可以在L2C上进行扫描和搜索。
至:
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
Integer externalid;
String externalname;
Integer internalid;
String internalname;
现在 Long id kind og 等于 externalid,我可以在 L2C 缓存中通过它进行搜索。