【问题标题】:Spring Data: JPA repository findAll() to return *Map instead of List?Spring Data:JPA 存储库 findAll() 返回 *Map 而不是 List?
【发布时间】:2025-11-30 15:10:01
【问题描述】:

我有一个 Spring Data JPA 存储库接口,看起来像这样:

@Repository
public interface DBReportRepository extends JpaRepository<TransactionModel, Long> {

    List<TransactionModel> findAll();
    List<TransactionModel> findByClientId(Long id);
}

除了要返回HashMap&lt;K, V&gt; 类型的集合之外,是否有解决方法可以做到这一点?我查看了 Spring Data 类,除了 List 返回值之外找不到任何东西。

【问题讨论】:

  • 没有,是什么阻止你自己做?
  • @isah 你的意思是自己为spring数据创建这样一个函数?
  • 为自己创建这样一个函数我的意思是,无论你在哪里调用这个存储库,在加载列表后,你都可以使用 Java 8 单线将其映射到 Map
  • Map is not a supported return type for Spring Data repository methods 所以下面@Patrick 的回答是正确的解决方案。
  • @DenissM.迭代会导致线性时间复杂度,反正你会得到,如果你需要访问每个项目,所以这不是问题:en.wikipedia.org/wiki/Time_complexity

标签: java spring-boot spring-data spring-data-jpa


【解决方案1】:

我认为您不会找到更简单的解决方案,即创建一个简单的单行线来将您的结果转换为地图。使用 java 8 lambdas 既简单又快速:

Map<Long, Transaction> transactionMap = transactionList.stream()
         .collect(Collectors.toMap(Transaction::getId, Function.identity()));

【讨论】:

    【解决方案2】:

    只需要解决类似的问题,帕特里克的回答有所帮助,但可以通过指出添加位置来改进它。

    为了使它看起来像 JPA 存储库返回一个映射,改进方法是将其包装在存储库接口中的默认方法中。无需在所有消费类中执行流。

    @Repository
    public interface DBReportRepository extends JpaRepository<TransactionModel, Long> {
    
        List<TransactionModel> findAll();
    
        default Map<Long, TransactionModel> findAllMap() {
            return findAll().stream().collect(Collectors.toMap(TransactionModel::getId, v -> v));
        }
    
        List<TransactionModel> findByClientId(Long id);
    
        default Map<Long, TransactionModel> findByClientIdMap(Long id) {
            return findByClientId(id).stream().collect(Collectors.toMap(TransactionModel::getId, v -> v));
        }
    }
    

    【讨论】:

    • 虽然我认为使用流将列表转换为地图的方法是一种简单而体面的方法,但它不属于存储库。存储库用于 CRUD 和查找器。转换是业务逻辑;因此,它属于服务代码,而不是存储库代码。作为软件开发人员,我们需要练习适当的关注点分离。
    【解决方案3】:

    另一种解决方案使用 java 8 lambdas:

    使用 Collectors 的 groupingBy 方法,按 ID 对 transactionList 进行分组并将结果存储在 Map 实例中

    Map<Long, Transaction> transactionMap = transactionList.stream().collect(Collectors.groupingBy(v->v.getId()));
    

    【讨论】:

    • 另一种解决方案如何?即使这不起作用,您是否对此进行了测试?
    • 当然,我测试过了。但是您无法实现直接在存储库中返回地图的方法。您需要在返回 List 的存储库类中实现该方法,然后获取此列表并将其转换为地图(使用上述代码)
    • 不,你没有测试它。至少不是您发布为返回类型 Map 的版本甚至都不正确。