在Spring Boot,Hibernate中使用@Query注释以JSON格式(键值对)查询结果

时间:2018-11-10 13:23:34

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

我的控制器

@GetMapping(value="/getAllDetails")
public List<PriceListEntity> getAllDetails() {
    return MyRepository.getAllDetails();
}

我的存储库

@Repository
public interface MyRepository extends CrudRepository<TestNativeQ, String> {
    @Query( value="SELECT qplt.name price_list_name,  qplab.status_code, qplab.start_date, (SELECT charge_definition_code FROM oalfsaas_repl.QP_CHARGE_DEFINITIONS_B WHERE charge_definition_id=qplab.charge_definition_id  ) chargedefinitioncode "
            + "FROM  PriceListEntity qplab, PriceListLineEntity qplt "
            + " WHERE qplab.price_list_id  =qplt.price_list_id ", nativeQuery = false)
    public List<PriceListEntity> getAllDetails();
}

实际结果:

[{"ABC", "DEF", "15/05/2018", "XXZ"}]

预期结果

[{name: "ABC", statuscode: "DEF", startDate: "15/05/2018", chargedefintioncode: "XXZ"}]

查询已联接了多个表,并且在列级别还进行了子查询。

1 个答案:

答案 0 :(得分:1)

您实际上正在使用选择进行投影,该选择不返回任何特定对象,而是返回一个元组,该元组是您在查询中选择的对象数组。无论采用哪种方式制作JSON,都没有名称,只有值。

您需要创建一个DTO来保存要通过JSON中的名称传递的值。

一个最小的示例,具有一个简单的实体,例如:

@Entity
@Getter
@RequiredArgsConstructor
public class TestClass {
    @Id
    @GeneratedValue
    private Long id;

    @NonNull
    private String a,b,c;
}

并且愿意通过-例如-仅ab可能会有DTO,如:

@RequiredArgsConstructor
public class TupleDto {
    @NonNull
    private String a,b;
}

以及您的情况PriceListDetailsDto

存储库可能声明为:

public interface TestClassRepository extends CrudRepository<TestClass, Long> {

    @Query(value="SELECT new org.example.TupleDto(tc.a, tc.b) FROM TestClass tc")
    List<TupleDto> fetchAB();

}

注意:上面是使用的运算符new和实体构造函数的完整路径。

通过这种方式,Spring存储库知道如何分配选定的字段,并且当从此DTO生成JSON时,将导致具有带有名称(DTO中的名称)的字段。

JPQL中的new运算符只是在Java中调用new,因此任何行数据a,b,c都可以用于构造Java对象,并且该对象的类构造函数接受相同的参数数量和类型(并且顺序相同),所以请new MyEntityObject(a,b,c)

注意:在这种简单情况下,如果原始实体被修改为在c中允许空值并添加相应的构造函数,则可以将其用作DTO。如果您的元组是由许多表构成的,则需要创建一个DTO来保存这些值。