如何将方法传入函数式接口以实现通用重试功能?
实现带重试的JPA Repository方法调用工具
1. 定义泛型函数式接口
针对JPA中findById、findByNumber这类单入参、泛型返回的查询方法,先定义通用函数式接口适配:
@FunctionalInterface public interface RepositoryQueryFunction<T, R> { R execute(T param); }
其中T为入参类型(如String、Integer),R为返回实体类型(如Employee、Record)。
2. 创建带重试的执行工具类
借助@Retryable实现数据库连接失败时的重试逻辑,工具类统一处理查询方法的执行:
import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Component; @Component public class RepositoryRetryHandler { // 捕获数据库访问异常,最多重试3次,每次间隔1秒 @Retryable( value = {org.springframework.dao.DataAccessException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000) ) public <T, R> R executeWithRetry(RepositoryQueryFunction<T, R> queryFunction, T param) { return queryFunction.execute(param); } }
value指定触发重试的异常范围,DataAccessException覆盖绝大多数数据库相关异常maxAttempts设置最大重试次数backoff配置重试间隔时间
3. 业务代码中使用示例
注入RepositoryRetryHandler,用方法引用直接传入JPA查询方法,替代直接调用:
@Service public class BusinessService { private final EmployeeRepository employeeRepository; private final RecordRepository recordRepository; private final RepositoryRetryHandler retryHandler; // 构造函数注入依赖 public BusinessService(EmployeeRepository employeeRepository, RecordRepository recordRepository, RepositoryRetryHandler retryHandler) { this.employeeRepository = employeeRepository; this.recordRepository = recordRepository; this.retryHandler = retryHandler; } public Employee getEmployeeById(String id) { // 替代直接调用employeeRepository.findById(id) return retryHandler.executeWithRetry(employeeRepository::findById, id) .orElseThrow(() -> new RuntimeException("Employee not found")); } public Record getRecordByNumber(Integer number) { // 替代直接调用recordRepository.findByNumber(number) return retryHandler.executeWithRetry(recordRepository::findByNumber, number); } }
4. 依赖与启动配置
确保项目引入Spring Retry相关依赖(以Maven为例):
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency>
并在启动类添加@EnableRetry开启重试功能:
import org.springframework.retry.annotation.EnableRetry; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableRetry public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
内容的提问来源于stack exchange,提问作者Wes
相关产品推荐
相关产品推荐

