JPA CriteriaQuery и множественный выбор одного поля возвращает список

#java #jpa #criteria-api #criteriaquery

Вопрос:

Мое прочтение javadoc для CriteriaQuery.multiselect заключается в том, что если я создаю запрос с помощью Object[].class, то независимо от того, сколько аргументов я передаю в multiselect, я всегда должен получать список объектов[]. Вариант 3 в приведенном ниже списке-единственный, который соответствует массиву чего-либо.

Однако в моем тесте это выглядит так, как будто используется вариант 4 или 5 в зависимости от количества выбранных полей.

Вопросы: Почему он это делает? Существует ли общий механизм, который я могу использовать, который всегда возвращает одну и ту же структуру результатов независимо от количества указанных полей?

Из CriteriaQuery.множественный выбор:

  1. Если тип запроса критериев CriteriaQuerylt;Tuplegt; (т. е. Объект запроса критериев, созданный либо методом createTupleQuery, либо путем передачи аргумента класса кортежа методу CreateQuery), объект кортежа, соответствующий аргументам метода множественного выбора, в указанном порядке будет создан и возвращен для каждой строки, которая является результатом выполнения запроса.
  2. Если тип запроса критериев относится CriteriaQuerylt;Xgt; к определяемому пользователем классу X (т. Е. объекту запроса критериев, созданному путем передачи аргумента класса X методу CreateQuery), аргументы метода множественного выбора будут переданы конструктору X, и экземпляр типа X будет возвращен для каждой строки.
  3. Если тип запроса критериев относится CriteriaQuerylt;X[]gt; к некоторому классу X, X[] для каждой строки будет возвращен экземпляр типа. Элементы массива будут соответствовать аргументам метода multiselect в указанном порядке.
  4. Если тип запроса критериев является CriteriaQuerylt;Objectgt; или если запрос критериев был создан без указания типа, и методу multiselect передается только один аргумент Object , для каждой строки будет возвращен экземпляр типа.
  5. Если тип запроса критериев является CriteriaQuerylt;Objectgt; или если запрос критериев был создан без указания типа, и методу multiselect передается более одного аргумента, экземпляр типа Object[] будет создан и возвращен для каждой строки. Элементы массива будут соответствовать аргументам метода множественного выбора в указанном порядке.

Я использую javax.persistence и впадаю в спячку от org.springframework.boot:spring-boot-starter-data-jpa -gt; 2.5.5 и org.hibernate:hibernate-core:5.4.32.Final

 @Entity @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class Thing {  @Id  Integer x;  String y; }  
 public interface ThingRepository extends CrudRepositorylt;Thing, Integergt;{ }  
 @Slf4j @AutoConfigureTestDatabase(replace=Replace.NONE) @DataJpaTest class ThingTest {  @PersistenceContext  EntityManager em;    @Test  void test() {  Thing thing = new Thing (3, "three");  em.persist(thing);    doit("x");  doit("x", "y");  }    void doit(String ... fields) {  CriteriaBuilder cb = em.getCriteriaBuilder();  CriteriaQuerylt;Object[]gt; cq = cb.createQuery(Object[].class);  Rootlt;Thinggt; root = cq.from(Thing.class);   Listlt;Selectionlt;?gt;gt; fieldList = new ArrayListlt;gt;();    for (var field : fields) {  fieldList.add(root.get(field));  }    cq.multiselect(fieldList);    TypedQuerylt;Object[]gt; query = em.createQuery(cq);    Listlt;Object[]gt; results = query.getResultList();    assertThat(results, hasSize(1));  Object obj = results.get(0);  log.info("result type = {}", obj.getClass());  }  }  
 Outputs:  result type = class java.lang.Integer  result type = class [Ljava.lang.Object;  

Side note: If you do this inside a custom repository method that supposedly is returning Listlt;Object[]gt; something in the repo proxy magic converts the list from Listlt;Integergt; to Listlt;Object[]gt; so it seems to work!?