Spring CrudRepository возвращает группу по результатам в виде карты - PullRequest
0 голосов
/ 15 октября 2019

Я использую CrudRepository для выполнения нативного запроса, где я использую сумму и группу по. Я хочу, чтобы запрос возвращал результат в виде карты (хэш). Мой запрос выглядит следующим образом:

 @Query(value = "SELECT l.currency, sum(l.price) as total_revenue from line l " + "where ol.id0 = :id0 and l.date_time between :dateStart and :dateEnd and " +
        "(cast(:id1 as text) is null or cast(l.id1 as text) = cast(:id1 as text)) and " +
        "(cast(:id2 as text) is null or cast(l.id2 as text) = cast(:id2 as text))" +
        "group by l.currency" ,
        nativeQuery = true)
List<Object[]> findTotalRevenueByCurrency(@Param("id0") UUID id0,
                                                     @Param("dateStart") Instant dateTimeStart,
                                                     @Param("dateEnd") Instant dateTimeEnd,
                                                     @Param("id1") UUID id1,
                                                     @Param("id2") UUID id2);

Это возвращает список объектов, которые я вручную превращаю в Map<String, BigDecimal>, используя следующий код:

var result = orderLineRepository.findAveragePriceByCurrency(id0, orderDate.minus(2, DAYS), orderDate.plus(2, DAYS), id1, id2);

Map<String, BigDecimal> revenueByCurrency = result.stream()
    .map(arr -> Map.of((String) arr[0], (BigDecimal) arr[1]))
    .flatMap(m -> m.entrySet().stream())
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));```

Что довольно хрупко и требуетКастинг. Есть ли способ, чтобы этот запрос возвращал Map<String, BigDecimal> из коробки?

1 Ответ

1 голос
/ 16 октября 2019

Вы можете создать собственный класс, соответствующий результат этого запроса, а затем отобразить список результатов на карте.

public class CustomQueryResult {
 //class properties
 public CustomQueryResult(String currency, BigDecimal price) {
    //assign 
 }
}
@Query(value = "SELECT new CustomQueryResult(l.currency, sum(l.price) as total_revenue) from line l " + "where ol.id0 = :id0 and l.date_time between :dateStart and :dateEnd and " +
        "(cast(:id1 as text) is null or cast(l.id1 as text) = cast(:id1 as text)) and " +
        "(cast(:id2 as text) is null or cast(l.id2 as text) = cast(:id2 as text))" +
        "group by l.currency" ,
        nativeQuery = true)
List<CustomQueryResult> findTotalRevenueByCurrency(@Param("id0") UUID id0,
                                                     @Param("dateStart") Instant dateTimeStart,
                                                     @Param("dateEnd") Instant dateTimeEnd,
                                                     @Param("id1") UUID id1,
                                                     @Param("id2") UUID id2);

var result = orderLineRepository.findAveragePriceByCurrency(id0, orderDate.minus(2, DAYS), orderDate.plus(2, DAYS), id1, id2);

 Map<String, BigDecimal> revenueByCurrency = result.stream()
                .collect(Collectors.toMap(k -> k.getCurrency(), v -> v.getPrice());
...