Spring Data:JPA 存储库 findAll() 返回 *Map 而不是 List?

问题描述 投票:0回答:5

我有一个 Spring Data JPA 存储库接口,如下所示:

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

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

是否有解决方法可以实现相同的效果,但要返回

HashMap<K, V>
类型的 Collection?我查看了 Spring Data 类,除了 List<> 返回值之外找不到任何内容。

java spring-boot spring-data spring-data-jpa
5个回答
48
投票

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

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

40
投票

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

为了使其看起来像 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));
    }
}

0
投票

您可以从自定义可流式包装类型获取地图,该类型记录在 Spring Data JPA 参考中。

@RequiredArgsConstructor(staticName = "of")
public class TransactionModels implements Streamable<TransactionModel> {
    
    private final Streamable<TransactionModel> streamable;

    @Override
    public Iterator<TransactionModel> iterator() {
        return streamable.iterator();
    }

    public Map<Long, TransactionModel> asMap() {
        return streamable.stream()
            .collect(Collectors.toMap(Transaction::getId, Function.identity()));
    }
}
@Repository
public interface DBReportRepository extends JpaRepository<TransactionModel, Long> {

    TransactionModels findAll();

    TransactionModels findByClientId(Long id);

}

在 Spring Data 中无法获取到你想要的

Map<Long, TransactionModel>
方法的原因是
java.util.Map<K,V>
默认会被委托给
org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution
而不是
org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution
。这是合理的,因为
Map
不是从 Java
 中的 
Collection
延伸而来。但就你而言,你想使用
Map
作为“集合”。幸运的是,您可以使用自定义方法扩展 Spring Data 存储库,它可以返回您喜欢的任何类型。


-1
投票

如果您想提高性能,在检索实体后创建地图并不是一个解决方案。与直接检索地图或列表相比,检索整个实体然后将所选字段添加到地图中需要更长的时间。


-2
投票

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

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

Map<Long, Transaction> transactionMap = transactionList.stream().collect(Collectors.groupingBy(v->v.getId()));
© www.soinside.com 2019 - 2024. All rights reserved.