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;