春季启动数据@query到DTO

时间:2018-11-15 14:58:24

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

我想将查询结果分配给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 :(得分:0)

首先,您可以查看Spring Data JPA文档,并在以下部分找到一些帮助:Class-based Projections (DTOs)

还有一个标题为避免投影DTO的样板代码的段落,他们建议您使用Lombok的@Value批注来生成不可变的DTO 。这与Lombok的@Data批注相似,但不可变。

如果将其应用于示例,则源代码将如下所示:

@Value
public class MetricDto {

    private int share;
    private int shareholder;

}

然后,因为您的查询是一个NativeQuery,请在您的Spring Data Repository中指定它。 您可以在文档Native Queries中找到帮助。 您将需要类似的东西:

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

答案 1 :(得分:0)

在我的项目中,我已经使用投影进行了如下所示:

@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()的返回类型正确,这可能会因数据库而异。