весенние данные загрузки @ запрос к DTO - PullRequest
0 голосов
/ 15 ноября 2018

Я хочу присвоить результат запроса объекту DTO.DTO выглядит так:

@Getter
@Setter
@NoArgsConstructor
public class Metric {
     private int share;
     private int shareholder;

      public Metric(int share, int shareholder) {
         this.share = share;
         this.shareholder = shareholder;
       }

 }

и выглядит следующим образом

@RepositoryRestResource(collectionResourceRel = "shareholders", path = 
      "shareholders")
public interface ShareholderRepository extends 
          PagingAndSortingRepository<Shareholder, Integer> {

   @Query(value = "SELECT new 
   com.company.shareholders.sh.Metric(SUM(s.no_of_shares),COUNT(*)) FROM 
   shareholders s WHERE s.attend=true")
   Metric getMetrics();


}

Однако это не работает, поскольку я получаю следующее исключение:

Caused by:org.hibernate.QueryException: could not resolve property: no_of_shares of:com.company.shareholders.sh.Shareholder[SELECT new com.company.shareholders.sh.Metric(SUM(s.no_of_shares),COUNT(*)) FROM com.company.shareholders.sh.Shareholder s WHERE s.attend=true]

Ответы [ 2 ]

0 голосов
/ 03 апреля 2019

В моем проекте я использовал проекции , как показано ниже:

@Repository
public interface PeopleRepository extends JpaRepository<People, Long> {

    @Query(value = "SELECT p.name AS name, COUNT(dp.people_id) AS count " +
        "FROM people p INNER JOIN dream_people dp " +
        "ON p.id = dp.people_id " +
        "WHERE p.user_id = :userId " +
        "GROUP BY dp.people_id " +
        "ORDER BY p.name", nativeQuery = true)
    List<PeopleDTO> findByPeopleAndCountByUserId(@Param("userId") Long userId);

    @Query(value = "SELECT p.name AS name, COUNT(dp.people_id) AS count " +
        "FROM people p INNER JOIN dream_people dp " +
        "ON p.id = dp.people_id " +
        "WHERE p.user_id = :userId " +
        "GROUP BY dp.people_id " +
        "ORDER BY p.name", nativeQuery = true)
    Page<PeopleDTO> findByPeopleAndCountByUserId(@Param("userId") Long userId, Pageable pageable);

}



// Interface to which result is projected
public interface PeopleDTO {

    String getName();

    Long getCount();

}

Поля из проецируемого интерфейса должны совпадать с полями в этой сущности.В противном случае отображение поля может нарушиться.

Также, если вы используете нотацию SELECT table.column, всегда определяйте псевдонимы, совпадающие с именами из объекта, как показано в примере.

В вашем случае измените @Query, как показано ниже:

@Query(value = "SELECT new 
   SUM(s.no_of_shares) AS sum,COUNT(*) AS count FROM 
   shareholders s WHERE s.attend=true", nativeQuery = true)
MetricDTO getMetrics();

И создайте interface MetricDTO, как показано ниже:

public interface MetricDTO {

    Integer getSum();

    Long getCount();

}

Также убедитесь, что тип возвращаемого значения getSum() и getCount() является правильным, это может варьироваться в зависимости не отбазы данных.

0 голосов
/ 16 ноября 2018

Во-первых, вы можете взглянуть на документацию Spring Data JPA, вы можете найти некоторую помощь в этом разделе: Проекции на основе классов (DTO) .

Существует также параграф, озаглавленный Избегайте шаблонного кода для проекций DTO , где они советуют использовать аннотацию @Value от Lombok, чтобы создать неизменный DTO . Это похоже на аннотацию Lombok @Data, но неизменное.

Если вы примените его к своему примеру, источник будет выглядеть так:

@Value
public class MetricDto {

    private int share;
    private int shareholder;

}

Затем, поскольку ваш запрос является NativeQuery, укажите его в репозитории данных Spring. Вы можете найти помощь в документации: Собственные запросы . Вам понадобится что-то вроде:

@Query(value = "SELECT new 
   com.company.shareholders.sh.MetricDto(SUM(s.no_of_shares),COUNT(*)) FROM 
   shareholders s WHERE s.attend=true", nativeQuery = true)
   MetricDto getMetrics();
...