JPQL: получение коллекции в выражении конструктора

Я использую JPQL и хочу получать некоторые обычные параметры и коллекцию в выражении конструктора, чтобы напрямую создавать объекты DTO. Но если коллекция пуста, я всегда получаю ошибку, потому что он не находит правильный конструктор:

Класс DTO выглядит следующим образом:

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;
}

И теперь выражение конструктора выглядит следующим образом:

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

Текущая проблема заключается в том, что если коллекция p.childs пуста, в ней говорится, что она не находит правильный конструктор, ему нужно (long, String, Child) вместо (long, String, Collection).

Есть ли у вас какое-либо решение или просто невозможно использовать сборку в выражении конструктора?

О, и еще одна вещь: если я легко создаю два конструктора (..., Collection childs AND..., Child childs), я не получаю никаких результатов, но ошибки тоже... в моих глазах не очень приятно:/

Ответ 1

Это не ответ.

Спецификация 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

A single_valued_path_expression - это то, что это звучит - выражение свойства, которое указывает на какой-то скаляр (например, p.id), a scalar_expression также является выражением, которое указывает на скаляр, a aggregate_expression применение функции типа sum, которая сводит многозначное выражение к скалярному, а identification_variable - это ссылка на тип, который вы запрашиваете. Ни один из них не может быть оценен по значению. Предполагая, что я правильно прочитал спецификацию.

Итак, если ваш поставщик JPA позволяет использовать параметр, определяющий значение коллекции, в выражении конструктора, это потому, что он выходит за пределы спецификации. Что очень приятно, но не то, на что вы обязательно можете положиться!

Ответ 2

Попробуйте,

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

Ответ 3

У меня была аналогичная проблема и я попытался "Объект" в конструкторе DTO, как предположил Джеймс, но передается дочерний объект, и кажется, что это только первый ребенок, а не ожидаемый список/массив детей.

Я закончил с "нормальным" запросом, создающим все DTO в цикле for.

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;