You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring JPA:如何创建仅含查询方法、无CRUD操作的JpaRepository?

这确实是个非常实用的场景——当已经有专门的仓库负责实体的增删改操作时,我们当然不想让统计类仓库带上一堆多余的CRUD方法,既显得冗余还容易误调用。Spring JPA完全有优雅的解决方案,根本不需要去重写方法抛异常,下面给你两个最常用的实现方式:

方案1:自定义只读基础仓库(推荐,可扩展)

首先创建一个标记为@NoRepositoryBean的基础接口,告诉Spring不要把它当作可实例化的仓库,你可以在里面放一些通用的只读方法(如果需要的话),也可以留空:

@NoRepositoryBean
public interface ReadOnlyRepository<T, ID> extends Repository<T, ID> {
    // 这里可以按需添加通用只读方法,比如:
    // Optional<T> findById(ID id);
}

然后让你的统计仓库继承这个自定义的只读接口,而不是JpaRepository:

@Repository
public interface StatisticRepo extends ReadOnlyRepository<PaymentList, Long> {
    @Query("SELECT pd.date, SUM(pd.totalPayment) " +
           "FROM PaymentDetails pd WHERE pd.date BETWEEN :date_from AND :date_until " +
           "GROUP BY pd.date")
    List<Object[]> getDailyExpensesStatistic(@Param("date_from") Date dateFrom, 
                                             @Param("date_until") Date dateUntil);
}

这样你的StatisticRepo就只会包含你自己定义的统计查询方法,完全没有CRUD相关的方法,干净又安全。

方案2:直接继承顶层Repository接口

如果你的统计仓库连通用的只读方法都不需要,那就更简单了——直接让仓库继承Spring Data最顶层的Repository<T, ID>接口,它本身没有任何默认方法,所以你的仓库只会有你自定义的@Query方法:

@Repository
public interface StatisticRepo extends Repository<PaymentList, Long> {
    @Query("SELECT pd.date, SUM(pd.totalPayment) " +
           "FROM PaymentDetails pd WHERE pd.date BETWEEN :date_from AND :date_until " +
           "GROUP BY pd.date")
    List<Object[]> getDailyExpensesStatistic(@Param("date_from") Date dateFrom, 
                                             @Param("date_until") Date dateUntil);
}

补充说明

之前你用JpaRepository会带上CRUD方法,是因为JpaRepository继承了CrudRepository和PagingAndSortingRepository,这两个接口自带了全套的增删改查及分页排序方法。而我们选择的Repository或自定义ReadOnlyRepository则完全避开了这些冗余方法,完美适配纯统计查询的场景。

另外,建议把返回值List改成List<Object[]>,因为你的查询返回了两个字段(日期和总金额),用泛型可以让类型更安全,后续处理结果时也更清晰。

内容的提问来源于stack exchange,提问作者Юрий Яхница

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 10:57:49