在 Spring 里,实现对 JPA 的二级缓存支持,一般可以按以下步骤操作:

1. 依赖添加

首先,你得在项目里添加 JPA 与二级缓存的依赖。若使用的是 Maven 项目,可在 pom.xml 中添加如下依赖:

<dependencies>
    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- Hibernate 二级缓存依赖 -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-ehcache</artifactId>
    </dependency>
    <!-- Ehcache 依赖 -->
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
    </dependency>
</dependencies>

2. 二级缓存配置

application.properties 或者 application.yml 文件中开启 JPA 的二级缓存,同时指定使用 Ehcache 作为二级缓存的实现。

application.properties 示例

# 开启 JPA 二级缓存
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
# 开启查询缓存
spring.jpa.properties.hibernate.cache.use_query_cache=true
# 指定二级缓存实现为 Ehcache
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory

application.yml 示例

spring:
  jpa:
    properties:
      hibernate:
        cache:
          use_second_level_cache: true
          use_query_cache: true
          region:
            factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory

3. Ehcache 配置文件创建

src/main/resources 目录下创建 ehcache.xml 文件,用于配置 Ehcache 的缓存策略。示例如下:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">

    <diskStore path="java.io.tmpdir"/>

    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
    </defaultCache>

    <!-- 为特定实体配置缓存 -->
    <cache name="com.example.entity.YourEntity"
           maxEntriesLocalHeap="500"
           eternal="false"
           timeToIdleSeconds="180"
           timeToLiveSeconds="180"
           memoryStoreEvictionPolicy="LFU">
    </cache>
</ehcache>

此配置文件定义了默认缓存策略,还为特定实体 com.example.entity.YourEntity 配置了缓存策略。

4. 实体类上启用二级缓存

在需要使用二级缓存的实体类上添加相应注解,示例如下:

import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class YourEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

这里的 @Cacheable 注解表明该实体类支持二级缓存,@Cache 注解则指定了缓存并发策略。

5. 测试二级缓存

你可以编写一个简单的测试方法来验证二级缓存是否生效:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;

@Service
public class YourEntityService {
    @Autowired
    private YourEntityRepository yourEntityRepository;

    @Transactional
    public YourEntity getEntityById(Long id) {
        return yourEntityRepository.findById(id).orElse(null);
    }
}

在调用 getEntityById 方法两次时,若二级缓存生效,第二次调用会直接从缓存中获取数据,而非再次查询数据库。

以下是完整的代码示例,包含了上述步骤中的关键代码:

YourEntity.java

import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class YourEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}    

YourEntityRepository.java

import org.springframework.data.jpa.repository.JpaRepository;
import com.example.entity.YourEntity;

public interface YourEntityRepository extends JpaRepository<YourEntity, Long> {
}    

YourEntityService.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;

@Service
public class YourEntityService {
    @Autowired
    private YourEntityRepository yourEntityRepository;

    @Transactional
    public YourEntity getEntityById(Long id) {
        return yourEntityRepository.findById(id).orElse(null);
    }
}    

ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">

    <diskStore path="java.io.tmpdir"/>

    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
    </defaultCache>

    <!-- 为特定实体配置缓存 -->
    <cache name="com.example.entity.YourEntity"
           maxEntriesLocalHeap="500"
           eternal="false"
           timeToIdleSeconds="180"
           timeToLiveSeconds="180"
           memoryStoreEvictionPolicy="LFU">
    </cache>
</ehcache>    

通过上述步骤,你就可以在 Spring 项目中实现对 JPA 的二级缓存支持。