Группа хранилища данных Spring по столбцам, список объектов с другими столбцами

Как заставить репозиторий Spring возвращать пользовательский DTS, который группируется по столбцу businessValue1 в таблице и имеет список объектов DTO с другими столбцами в таблице

Таблица, из которой я хочу вернуть ДТС

id | businessValue1 | businessValue2 | businessValue3
1  | "x"            | "uigaiun"      | "guthgi"
2  | "x"            | "rktjuhngit"   | "ujgthniuertn"
3  | "x"            | "nguitren"     | "ikljugnbe"
4  | "y"            | "iughnuitn"    | "eiubgnuie"
5  | "q"            | "rtiluhn"      | "iljughbl"
6  | "q"            | "tkiruln"      | "jutgnhet"

Класс Java Entity, представляющий таблицу

@Data
@AllArgsConstructor
@Entity
public class SomeEntity {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @NotNull
  private long id;
  
  @NotNull
  private String businessValue1;
  
  @NotNull
  private String businessValue2;
  
  @NotNull
  private String businessValue3;
}

Целевые классы:

DTO представляет другие столбцы в таблице.

@Data
@AllArgsConstructor
public class SomeDTO {

  private String businessValue2;
  
  private String businessValue3;
}

DTS представляет группу столбца businessValue1 с другими столбцами в виде списка DTO.

@Data
@AllArgsConstructor
public class SomeDTS {

  private String businessValue1;
  
  private List<SomeDTO> dtos;
}

Мой ожидаемый результат будет иметь структуру, как показано ниже

├── "x"
|    ├── "uigaiun", "guthgi"
|    ├── "rktjuhngit", "ujgthniuertn"
|    └── "nguitren", "ikljugnbe"
|
├── "y"
|    └── "iughnuitn", "eiubgnuie"
|
└── "q"
     ├── "rtiluhn", "iljughbl"
     └── "tkiruln", "jutgnhet"

Я думал, что интерфейс Spring Data Repository должен выглядеть примерно так:

@Repository
public interface SomeEntityRepository extends JpaRepository<SomeEntity, Long> {

  @Query(
      "SELECT "
      +  "new SomeDTS "
      +"FROM "
      +  "SomeEntity s "
      +"GROUP BY "
      +  "s.businessValue1")
  public List<SomeDTS> SomeEntityGroupByBusinessValue1();

}

Я изо всех сил пытаюсь правильно выполнить запрос JPQL, может ли кто-нибудь мне помочь?

ОБНОВЛЕНИЕ 1 – 19 ноября 2020 г.

Я думаю, что стал немного ближе с комментарием от @Zorglube

@Repository
public interface SomeEntityRepository extends JpaRepository<SomeEntity, Long> {

  @Query(value =
      "SELECT "+
          " DISTINCT SomeDTS.businessValue1, SomeDTO" +
          " FROM SomeEntity AS SomeDTS" +
          " JOIN SomeEntity AS SomeDTO ON SomeDTS.businessValue1 = SomeDTO.businessValue1")
  Stream<SomeDTS> SomeEntityGroupByBusinessValue1();

}

Это все еще вызывает у меня проблемы с отображением

No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [SomeDts]
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [SomeDts]
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)
    at org.springframework.data.repository.query.ResultProcessor$ProjectingConverter.convert(ResultProcessor.java:297)
    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.lambda$and$0(ResultProcessor.java:217)
    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:228)
    at org.springframework.data.repository.query.ResultProcessor.lambda$processResult$0(ResultProcessor.java:163)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
    at org.hibernate.query.spi.StreamDecorator.collect(StreamDecorator.java:211)    
.
.
.

Итак, как сделать отображение?

Обновление 2 Вместо этого переключение на интерфейсы

@Repository
public interface SomeEntityRepository extends JpaRepository<SomeEntity, Long> {

  @Query(value =
      "SELECT "+
          " DISTINCT SomeDTSIF.businessValue1 as businessValue1, SomeDTOIF" +
          " FROM SomeEntity AS SomeDTSIF" +
          " JOIN SomeEntity AS SomeDTOIF ON SomeDTSIF.businessValue1 = SomeDTO.businessValue1")
  Stream<SomeDTSIF> SomeEntityGroupByBusinessValue1();

}

Решить проблему с конвертером, способным конвертировать, не найдено, но я получаю обратно 6 объектов:

├── "x"
|    └── NULL
|
├── "x"
|    └── NULL
|
├── "x"
|    └── NULL
|
├── "y"
|    └── NULL
|
├── "q"
|    └── NULL
|
└── "q"
     └── NULL

И список SomeDTOIF в SomeDTSIF не отображается.


person Nicolai Guido Klausen    schedule 16.11.2020    source источник
comment
Вам следует заглянуть в Projection или добавить некоторую информацию о сопоставлении в два файла Dts.   -  person Zorglube    schedule 16.11.2020
comment
Спасибо, я безуспешно пытался найти, кто занимается такой проекцией... То, что я нашел, на самом деле не охватывает то, что я пытаюсь: baeldung.com/spring-data-jpa-projections bytestree.com/spring/ docs.spring.io/spring-data/jpa/docs/current/reference/html / Шкаф, кажется, thorben-janssen.com/spring -data-jpa-query-projections Не могли бы вы указать на некоторые руководства.   -  person Nicolai Guido Klausen    schedule 18.11.2020


Ответы (1)


В итоге я создал виртуальный родительский объект, который действует как представление.

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
@EqualsAndHashCode
@Immutable
@Subselect(
    "SELECT"
        + " DISTINCT SomeEntityParent.currency_source "
        + " FROM some_entity SomeEntityParent"
        + " JOIN some_entity SomeEntity"
        + " ON SomeEntityParent.businessValue1 = SomeEntityParent.businessValue1"
)
public class SomeEntityParent {

  private String businessValue1;
  
  private List<SomeEntity> someEntity;
}

И затем интерфейс репозитория, основанный на этом

@Repository
public interface SomeEntityParentRepository extends JpaRepository<SomeEntityParent, Long> {

}

Которые потом можно использовать в сервисах

@Autowired
private SomeEntityParentRepository repository;
  
List<SomeEntityParent> results = repository.findAll();

Плоская структура теперь является иерархическим объектом.

person Nicolai Guido Klausen    schedule 20.11.2020