Я пытаюсь выяснить, как сделать DTO-проекцию сущности со списком Enums (@ElementCollection). К сожалению, документация QueryDsl отсутствует, и здесь я нахожу только результаты для версии 3, которые не применимы для версии 4.
@Entity
public class User {
private String username;
@Enumerated(EnumType.STRING)
@ElementCollection(targetClass = Permission.class)
private Set<Permission> permissions;
}
И я хотел бы DTO с набором / list / array либо Permission-Enums или просто Strings (будет преобразован в JSON в любом случае). Простое выражение конструктора не работает:
List<UserDto> users = new JPAQueryFactory(eM).select(
Projections.constructor(UserDto.class,
QUser.user.username, QUser.user.permissions))
.from(QUser.user)
.fetch();
Дает мне org.hibernate.QueryException: not an entity
Все примеры с .transform()
, которые я видел, используют groupBy и возвращают Map. Я генерирую эти запросы динамически, и мне нужен Список DTO, а не иногда Список DTO, а иногда и Карта. PostgreSQL query:
select id, username, array_remove(array_agg(up.permissions), null) as permissions
from users u
left join users_permissions up on up.uid = u.id
group by u.id;
EDIT 2:
Полагаю, это то, что мне нужно сделать с JPQL? : puke:
List<UserDto> users = (List<UserDto>) eM.getEntityManager().createQuery(
"SELECT u.id, u.username, u.tenantId, u.fullname, u.active, u.localeKey, perms " +
"FROM User u " +
"LEFT JOIN u.permissions perms")
.unwrap(org.hibernate.query.Query.class)
.setResultTransformer(
new ResultTransformer() {
private Map<Long, UserDto> res = new HashMap<>();
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
UserDto u = res.get(tuple[0]);
if (u == null) {
u = new UserDto((Long) tuple[0], (String) tuple[1], "", (String) tuple[2], (String) tuple[3], (boolean) tuple[4], (String) tuple[5], EnumSet.of((Permission) tuple[6]));
res.put(u.getId(), u);
} else {
u.getPermissions().add((Permission) tuple[6]);
}
return null;
}
@Override
public List<UserDto> transformList(List tuples) {
return new ArrayList<>(res.values());
}
})
.getResultList();