#java #jpa #criteria-api #criteriaquery
Вопрос:
Мое прочтение javadoc для CriteriaQuery.multiselect заключается в том, что если я создаю запрос с помощью Object[].class, то независимо от того, сколько аргументов я передаю в multiselect, я всегда должен получать список объектов[]. Вариант 3 в приведенном ниже списке-единственный, который соответствует массиву чего-либо.
Однако в моем тесте это выглядит так, как будто используется вариант 4 или 5 в зависимости от количества выбранных полей.
Вопросы: Почему он это делает? Существует ли общий механизм, который я могу использовать, который всегда возвращает одну и ту же структуру результатов независимо от количества указанных полей?
Из CriteriaQuery.множественный выбор:
- Если тип запроса критериев
CriteriaQuerylt;Tuplegt;
(т. е. Объект запроса критериев, созданный либо методом createTupleQuery, либо путем передачи аргумента класса кортежа методу CreateQuery), объект кортежа, соответствующий аргументам метода множественного выбора, в указанном порядке будет создан и возвращен для каждой строки, которая является результатом выполнения запроса. - Если тип запроса критериев относится
CriteriaQuerylt;Xgt;
к определяемому пользователем классу X (т. Е. объекту запроса критериев, созданному путем передачи аргумента класса X методу CreateQuery), аргументы метода множественного выбора будут переданы конструктору X, и экземпляр типа X будет возвращен для каждой строки. - Если тип запроса критериев относится
CriteriaQuerylt;X[]gt;
к некоторому классу X,X[]
для каждой строки будет возвращен экземпляр типа. Элементы массива будут соответствовать аргументам метода multiselect в указанном порядке. - Если тип запроса критериев является
CriteriaQuerylt;Objectgt;
или если запрос критериев был создан без указания типа, и методу multiselect передается только один аргументObject
, для каждой строки будет возвращен экземпляр типа. - Если тип запроса критериев является
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!?