Результат запроса в формате JSON (пара ключ-значение) при использовании аннотации @Query в Spring Boot, Hibernate
Мой контроллер
@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 ответ
Вы фактически делаете проекцию с вашим выбором, который не возвращает никакого конкретного объекта, но кортеж, который является массивом объектов, которые вы выбираете в своем запросе. Независимо от того, как устроен JSON, нет имен, только значения.
Вам нужно создать DTO для хранения значений, которые вы хотите передать по именам в вашем JSON.
Минимальный пример, имеющий простую сущность, такую как:
@Entity
@Getter
@RequiredArgsConstructor
public class TestClass {
@Id
@GeneratedValue
private Long id;
@NonNull
private String a,b,c;
}
и желающих пройти - например - только a
& b
там может быть 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 знает, как назначать выбранные поля, и при создании JSON из этого DTO получаются поля с именами (имена в DTO).
new
оператор в JPQL просто звонит new
в java- так что любой ряд данных a,b,c
может использоваться для конструирования объекта Java с помощью конструктора класса этого объекта, принимающего одинаковое количество параметров и типы (и в том же порядке), поэтому new MyEntityObject(a,b,c)
,
ВНИМАНИЕ ТАКЖЕ: в этом простом случае исходный объект мог бы использоваться как DTO, если бы он был изменен, чтобы разрешить нулевое значение в c и добавить соответствующий конструктор. В вашем случае, когда ваш кортеж состоит из множества таблиц, вам нужно создать DTO для хранения этих значений.