简体   繁体   English

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

[英]Spring Data: JPA repository findAll() to return *Map instead of List?

I have a Spring Data JPA repository interface that looks something like this:我有一个 Spring 数据 JPA 存储库界面,看起来像这样:

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

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

Is there a workaround to make the same but for a Collection to be returned of type HashMap<K, V> ?是否有一种解决方法可以实现相同但要返回类型为HashMap<K, V>的 Collection ? I've looked through the Spring Data classes and couldn't find anything other than List<> return values.我查看了 Spring 数据类,除了 List<> 返回值外找不到任何其他内容。

I dont think you will find an easier solution as to create a simple one liner to convert your result to a map. 我不认为你会找到一个更简单的解决方案,创建一个简单的一个班轮,将你的结果转换为地图。 It is simple and fast with java 8 lambdas: 使用java 8 lambdas简单快捷:

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

Just had to solve something similar and Patricks answer helped but it can be improved by indicating where to add it. 只需解决类似问题并且Patricks的回答有所帮助,但可以通过指示添加它的位置来改进。

To to make it appear like the JPA repo returns a map, an improvement would to wrap this up in a default method in the repository interface. 为了使它看起来像JPA repo返回一个映射,一个改进是将它包装在存储库接口的默认方法中。 Saves you having to perform a stream in all the consuming classes. 节省您必须在所有消费类中执行流。

@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));
    }
}

Creating a map after having retrieved your entities is not a solution if you are trying to improve your performance.如果您试图提高性能,则在检索实体后创建 map 不是解决方案。 It will take longer to retrieve the whole entity and then add the selected fields into a map, than to directly retrieve a map, or a list.与直接检索 map 或列表相比,检索整个实体然后将所选字段添加到 map 中需要更长的时间。

You could get your map from a custom streamable wrapper type which is documented in Spring Data JPA reference .您可以从Spring 数据 JPA 参考中记录的自定义流式包装器类型中获取 map。

@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);

}

The reason why you cannot get your desired Map<Long, TransactionModel> method in Spring Data is that java.util.Map<K,V> will be delegated to org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution instead of org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution by default.您无法在 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默认情况下。 And it's reasonable becuase Map is not extending from Collection in Java .这是合理的,因为Map没有从 Java 中的Collection扩展 But in your case you would like to use Map as a "collection".但在您的情况下,您希望将Map用作“集合”。 Fortunately you can extend Spring Data repository with custom methods which could return any type you like.幸运的是,您可以使用可以返回您喜欢的任何类型的自定义方法来扩展 Spring 数据存储库

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

Using a groupingBy method of Collectors that grouping transactionList by ID and storing results in a Map instance使用 Collectors 的groupingBy方法,按 ID 对 transactionList 进行分组并将结果存储在 Map 实例中

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM