有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JPA CriteriaQuery<Object[]。类>和单个字段的多选返回列表<Object>

我阅读了javadoc的CriteriaQuery。multiselect是指如果使用Object[]创建查询。类,则无论我向multiselect传递了多少个参数,我都应该始终获得对象[]的列表。下面列表中的选项3是唯一匹配某个数组的选项

然而,在我的测试中,根据所选字段的数量,似乎正在使用选项4或5

问题:它为什么这样做?我是否可以使用一种通用机制,它总是返回相同的结果结构,而不管指定的字段数是多少

来自CriteriaQuery。多选:

  1. 如果条件查询的类型为CriteriaQuery<Tuple>(即,通过createTupleQuery方法或通过将元组类参数传递给createQuery方法创建的条件查询对象),则为与multiselect方法的参数相对应的元组对象,按指定顺序,将为查询执行产生的每一行实例化并返回
  2. 如果某个用户定义类X的条件查询类型为CriteriaQuery<X>(即,通过将X类参数传递给createQuery方法创建的条件查询对象),则多选择方法的参数将传递给X构造函数,并且将为每一行返回类型为X的实例
  3. 如果某个类X的条件查询的类型为CriteriaQuery<X[]>,则将为每一行返回类型为X[]的实例。数组的元素将按照指定的顺序与multiselect方法的参数相对应
  4. 如果条件查询的类型为CriteriaQuery<Object>,或者如果创建条件查询时未指定类型,并且只向multiselect方法传递了一个参数,则将为每一行返回类型为Object的实例
  5. 如果条件查询的类型为CriteriaQuery<Object>,或者如果创建条件查询时未指定类型,并且向multiselect方法传递了多个参数,则将实例化类型为Object[]的实例,并为每一行返回该实例。数组的元素将按照指定的顺序与multiselect方法的参数相对应

我正在使用javax.persistence并从 org.springframework.boot:spring-boot-starter-data-jpa -> 2.5.5org.hibernate:hibernate-core:5.4.32.Final

@Entity @Getter @Setter @NoArgsConstructor @AllArgsConstructor
public class Thing {
    @Id
    Integer x;
    String y;
}
public interface ThingRepository extends CrudRepository<Thing, Integer>{
}
@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();
        CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
        Root<Thing> root = cq.from(Thing.class);

        List<Selection<?>> fieldList = new ArrayList<>();
        
        for (var field : fields) {
            fieldList.add(root.get(field));
        }
        
        cq.multiselect(fieldList);
        
        TypedQuery<Object[]> query = em.createQuery(cq);
        
        List<Object[]> 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;

旁注:如果您在一个自定义存储库方法中执行此操作,该方法可能返回List<Object[]>,那么repo代理魔术中的某些东西会将列表从List<Integer>转换为List<Object[]>,因此它似乎可以工作


共 (0) 个答案