几天来,我一直在try 将我的旧项目从Springboot 2 / Hibernate 5 / EHCache 2迁移到更新的Java 17 / Springboot 3 / Hibernate 6 / EHCache 3.

当然,我已经阅读了大量文档,try 了许多配置和依赖项设置.我还调试了这些库,以找出问题的原因.

在发布代码的相关部分之前,我想列出我试图解决的问题:

  1. 项目启动,配置被解析(我通过调试看到了这一点),EHCache侦听器被注册,但是当从数据库获取数据时,它被存储在缓存中,但是侦听器不触发.
  2. 尽管有1 minute TTL英镑,但储存的物品永远不会过期.
  3. 通过调试,我看到DemoEntity EHCache配置初始化了两次:从之前的JCache,然后通过Hibernate本身(这个流可能是上述一些问题的根本原因).

我知道在您掌握的信息如此之少的情况下回答问题并不容易,但我相信您能告诉我,我是否在依赖项包含、应用程序配置(application.yaml)或代码本身方面犯了任何明显的错误.

它遵循相关的代码部分.

提前谢谢您!

pom.xml

<properties>
    <springboot.version>3.1.2</springboot.version>
    <ehcache.version>3.10.8</ehcache.version>
    <hibernate.version>6.2.2.Final</hibernate.version> <!-- As for the current version of springboot -->
</properties>

<dependencies>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>

  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-cache</artifactId>
      <version>${springboot.version}</version>
  </dependency>

  <dependency>
      <groupId>org.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>${ehcache.version}</version>
      <classifier>jakarta</classifier>
  </dependency>

  <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-jcache</artifactId>
      <version>${hibernate.version}</version>
  </dependency>
</dependencies>

application.yaml

spring:
  cache:
    jcache:
      config: file:///app/config/ehcache.xml

  jpa:
    properties:
      hibernate:
        cache:
          region.factory_class: org.hibernate.cache.jcache.internal.JCacheRegionFactory
          use_second_level_cache: true
          use_query_cache: true

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'
    xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.10.xsd"
>
    <cache-template name="entitiesDefault">
        <expiry>
            <ttl unit="minutes">1</ttl>
        </expiry>

        <listeners>
            <listener>
                <class>api.demo.springboot.framework.persistence.JpaCacheEventListener</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>ORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>EVICTED</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>UPDATED</events-to-fire-on>
            </listener>
        </listeners>

        <resources>
            <heap unit="entries">1000</heap>
        </resources>
    </cache-template>

    <cache-template name="entitiesRelationsDefault">
        <expiry>
            <ttl unit="minutes">1</ttl>
        </expiry>

        <listeners>
            <listener>
                <class>api.demo.springboot.framework.persistence.JpaCacheEventListener</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>ORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>EVICTED</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>UPDATED</events-to-fire-on>
            </listener>
        </listeners>

        <resources>
            <heap unit="entries">1000</heap>
        </resources>
    </cache-template>

    <cache-template name="queriesDefault">
        <expiry>
            <ttl unit="minutes">1</ttl>
        </expiry>

        <listeners>
            <listener>
                <class>api.demo.springboot.framework.persistence.JpaCacheEventListener</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>ORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>EVICTED</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>UPDATED</events-to-fire-on>
            </listener>
        </listeners>

        <resources>
            <heap unit="entries">1000</heap>
        </resources>
    </cache-template>

    <cache
        alias="default-update-timestamps-region"
    >
        <expiry>
            <ttl unit="minutes">1</ttl>
        </expiry>

        <listeners>
            <listener>
                <class>api.demo.springboot.framework.persistence.JpaCacheEventListener</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>ORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>EVICTED</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>UPDATED</events-to-fire-on>
            </listener>
        </listeners>

        <resources>
            <heap unit="entries">1000</heap>
        </resources>
    </cache>

    <cache
        alias="default-query-results-region"
        uses-template="queriesDefault"
    />

    <cache
        alias="DemoEntity"
        uses-template="entitiesDefault"
    >
        <value-type>api.demo.springboot.application.persistence.entities.DemoEntity</value-type>
    </cache>
</config>

DemoEntity.java

import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.springframework.cache.annotation.Cacheable;

import java.io.Serializable;

@Data

@Entity
@Table(name = "DEMO_TABLE")

@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class DemoEntity implements Serializable {
    private static final long serialVersionUID = 0L;

    @Id
    @Column(name = "ID")
    private Integer id;

    @Column(name = "DESCRIPTION")
    private String description;

}

JpaCacheEventListener.java

import lombok.extern.slf4j.Slf4j;
import org.ehcache.event.CacheEvent;
import org.ehcache.event.CacheEventListener;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class JpaCacheEventListener implements CacheEventListener<Object, Object> {

    @Override
    public void onEvent(CacheEvent event) {
        if (log.isTraceEnabled()) {
            log.trace(
                "{ type: {}, key: {} }",
                event.getType(),
                event.getKey()
            );
        }
    }

}

推荐答案

我终于找到了解决所有问题的办法.

我向张贴的源代码报告ONLY the fixes:

application.yaml

spring:
  jpa:
    properties:
      hibernate:
        cache:
          region.factory_class: org.hibernate.cache.jcache.internal.JCacheRegionFactory
          use_second_level_cache: true
          use_query_cache: true

        javax:
          cache:
            provider: org.ehcache.jsr107.EhcacheCachingProvider
            uri: file:///app/config/ehcache.xml
          missing_cache_strategy: fail

ehcache.xml

    <!-- Entities (Mandatory: alias must be a FQDN of the entity in order to properly instantiate the cache as configured here!)-->

    <cache
        alias="it.sisal.betting.api.demo.springboot.application.persistence.entities.DemoEntity"
        uses-template="entitiesDefault"
    />

不,一切正常!

Java相关问答推荐

获取拦截器内部的IP地址

如何为具有多对多关系的实体的给定SQL查询构建JPA规范?

我想了解Java中的模块化.编译我的应用程序时,我有一个ResolutionException

Springdoc Whitelabel Error Page with Spring V3

如何转换Tue Feb 27 2024 16:35:30 GMT +0800 String至ZonedDateTime类型""

为什么在枚举中分支预测比函数调用快?

JVM会优化这个数学运算吗?

SpringBoot+Java 17@Valid未验证POJO

更新GWT 2.5.1到2.11.0和sencha GXT 3.1.1到4.1时出现错误

为什么Java Annotation接口覆盖对象类中的方法

Spark忽略Iceberg Nessie目录

由于我在Main方法中关闭了 scanner ,但在该方法中创建了一个新的 scanner ,因此出现了错误

返回响应时,CamelCase命名约定不起作用

用户填充的数组列表永不结束循环

如何在antlr4中跳过所有反斜杠-换行符而保留换行符?

如何从日期中截取时间并将其传递给组件?

Java17支持哪个MapR版本?

Kotlin-仅替换字符串中最后一个给定的字符串

我无法在我的Spring Boot应用程序中导入CSV依赖项

Bash数组的单引号元素并使用空格连接