如何将JPA创建的本机查询映射到投影

问题描述

我正在尝试使用Spring Data JPA createNativeQuery从postgresql数据库获取计数。但是,查询返回的是null而不是实际值。

这是下面的JPA createNativeQuery语句:

Query q = entityManager.createNativeQuery("SELECT null AS id,count(case when (IS_QUERIED = false AND SUBMITTED = true) 
then 1 else null end) AS pending,count(case when ( (SUBMITTED = true)) then 1 else null end) AS submitted,count(*) AS totalApplications FROM ANNUAL_RETURNS ",AnnualReturn.class);
//Note: AnnualReturn is the name of the @Entity class

List <AnnualReturn> countList=q.getResultList();

return countList;

我需要帮助,将查询中的“已提交”,“待处理”和“ totalApplications”实例映射为返回结果的方式。

预期结果是:

"data": {
        "totalApplications": 2000,"submitted": 560,"pending": 60,}

结果越来越好了

{
    "data": [
        null
    ]

我将不胜感激。

解决方法

您不应在此处使用输入查询,请尝试类似

Query q = entityManager.createNativeQuery("SELECT " +
  " COALESCE(sum(case when (IS_QUERIED = false AND SUBMITTED = true) " +
  " then AMOUNT else 0 end),0) AS pending," +
  " COALESCE(sum(case when ( (SUBMITTED = true)) then 1 else 0 end),0) AS submitted," +
  " COALESCE(sum(AMOUNT),0) AS totalApplications FROM ANNUAL_RETURNS ");

List <Object[]> countList=q.getResultList();

Object[] obj = countList.get(0);

for (Object value : obj) {
     System.out.println(value);
}
long pending = ((BigInteger)obj[0]).longValue();
long submitted = ((BigInteger)obj[1]).longValue();
long total = ((BigInteger)obj[2]).longValue();


return ...; // prepare the values to your convinience

编辑

将null更改为0,以避免结果中可能存在null值

编辑

将NPE固定在空表上

,

我不知道为什么,但是我相信SELECT null AS id导致获取空记录。

如果您不希望获取ID,则可以将投影与自定义RowMapper或DTO投影一起使用。

见下文:

@Entity
@Data
@ToString
class A {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
    String name;
    int age;

    public A() {
    }
    public A(String name,int age) {
        this.name = name;
        this.age = age;
    }
}

interface ARepo extends JpaRepositoryImplementation<A,Long> {
}

@Component
@RequiredArgsConstructor
class Init {
    final ARepo repo;
    final EntityManager em;

    @EventListener
    public void init(ContextRefreshedEvent evt) {
        repo.save(new A("XX",5));
        repo.save(new A("ZZ",6));
        repo.save(new A("AA",11));
        repo.save(new A("AB",12));

        Query q = em.createNativeQuery("select 0 as id,a.name as name,a.age as age  from A a where a.total > 10 ",A.class);

        System.out.println(q.getResultList()); //fetches AA and BB 
        //if you change the query to select null as id  it would return [ null,null]
          
    }
}