JPQL: получение коллекции в выражении конструктора - PullRequest
12 голосов
/ 14 мая 2011

Я использую 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 и ..., Child childs), я не получаю никаких результатов, но и ошибок тоже нет ... в моих глазах не очень приятно: -/

Ответы [ 3 ]

11 голосов
/ 14 мая 2011

Это не ответ.

Спецификация 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), scalar_expression также является выражением, которое указывает на скаляр, aggregate_expression - это применение функции, подобной sum, которая уменьшает многозначное выражение до скалярного, а identification_variable является ссылкой на тип, к которому вы обращаетесь. Ни один из которых не может быть оценен коллекцией. Предполагая, что я прочитал спецификацию правильно.

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

3 голосов
/ 16 мая 2011

Попробуйте,

public DTO (long id, String name, Object children)
2 голосов
/ 22 октября 2014

У меня была похожая проблема, и я попытался использовать «Объект» в конструкторе 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;
...