问题 JPQL:在构造函数表达式中接收集合


我正在使用JPQL并希望在Constructor Expression中接收一些常规参数和集合以直接创建DTO对象。但是如果Collection是空的,我总是会收到一个错误,因为他找不到合适的构造函数:

DTO-Class看起来如下:

public class DTO {
    private long id;
    private String name;
    private Collection<Child> children;

    public DTO (long id, String name, Collection<Child> children){
    this.id = id;
    this.name = name;
    this.children= children;
    }
}

儿童班:

public class Child {
    private String name;
    private int age;
}

现在,Constructor Expression看起来如下:

return (List<DTO>) getEm().createQuery("SELECT DISTINCT NEW de.DTO(p.id, p.name, p.childs) 
                                          FROM Parent p").getResultList();

目前的问题是,如果Collection p.childs为空,它表示它找不到正确的构造函数,它需要(long,String,Child)而不是(long,String,Collection)。

您有任何解决方案,或者根本无法在构造函数表达式中使用Collection?

哦,还有一件事:如果我轻松创建两个构造函数(...,Collection childs AND ...,Child childs)我没有得到任何结果,但也没有错误......在我看来并不是很满意: - /


9847
2018-05-13 22:32


起源

我想你已经忘了发帖了 Parent 类。也是复数形式的 child 是 children。 - Behrang
你有没有尝试添加条件来查询 - “哪里的孩子不是空的和大小(p.childs)<> 0” - Nayan Wadekar


答案:


这不是答案。

据我所知,JPA 2.0规范不允许在构造函数表达式中使用集合作为参数。 4.8节定义了一个这样的构造函数表达式:

constructor_expression ::=
        NEW constructor_name ( constructor_item {, constructor_item}* )
constructor_item ::=
        single_valued_path_expression |
        scalar_expression |
        aggregate_expression |
        identification_variable

一个 single_valued_path_expression 它听起来像是一个属性表达式,指向某种标量(例如 p.id), 一个 scalar_expression 也是指向标量的表达式,a aggregate_expression 是一个像函数的应用程序 sum 它将多值表达式减少为标量值,并且 identification_variable 是您查询的类型的引用。这些都不是收藏价值的。假设我已经阅读了规范。

因此,如果您的JPA提供程序允许您在构造函数表达式中使用集合值参数,那是因为它超出了规范。这是非常好的,但不是你必须依赖的东西!


9
2018-05-14 18:46



嘿汤姆安德森,非常感谢你提供这方面的信息。我只是使用Eclipse Link,所以我猜,不使用Hibernate或其他东西,它也会在更高层上运行,我不会成功。 @评论:是的,我忘记了父类,但我也只有一个id,一个名字和一个有或没有孩子的集合。因此,IS NOT EMPTY等条件不符合我的目标,我也需要没有孩子的父母。谢谢你的帮助。 - Florian
与JPA 2.1相同,请参见章节4.14 BNF,第211页。 - Arend v. Reinersdorff


尝试,

public DTO (long id, String name, Object children)

3
2018-05-16 15:06





我遇到了类似的问题,并在James建议的DTO构造函数中尝试了“Object”,但是传入了一个子对象,它似乎只是第一个子节点,而不是预期的子节点List / Array。

我最终得到一个“正常”查询,在for循环中创建所有DTO。

TypedQuery<Parent> query = em.createQuery("SELECT p FROM Parent p", Parent class);
        List<Parent> list = query.getResultList();
        List<DTO> result = new ArrayList<>();
        for (Parent p : list)
        {
            DTO dto = new DTO();
            //set dto props and fill collection
            result.add(obj);
        }
        return result;

1
2017-10-22 09:32