我正在尝试如何对带有枚举(@ElementCollection)列表的实体进行DTO投影。不幸的是,缺少QueryDsl文档,在这里我只找到版本3的结果,该结果not适用于版本4。
@Entity
public class User {
private String username;
@Enumerated(EnumType.STRING)
@ElementCollection(targetClass = Permission.class)
private Set<Permission> permissions;
}
而且我想要一个DTO,它的集合/列表/数组是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列表,有时一个Map。
编辑:
如果我要编写本机PostgreSQL查询,则类似:
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;
编辑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();
好的,我终于明白了。在这种情况下,您实际上必须使用一个转换器,因为您要聚合多行。]
我不得不深入研究QueryDsl's unit tests。如果您不使用IDE,那么静态导入实际上会使它变得棘手,但请像我一样在Github上阅读它。我几乎有了解决方案,但我使用了Expressions.set()
,而不是GroupBy.set()
:
List<UserDto> users = new JPAQueryFactory(eM.getEntityManager()) .selectFrom(QUser.user) .leftJoin(QUser.user.permissions, perm) .transform( groupBy(QUser.user.id) .list(Projections.constructor(UserDto.class, QUser.user.id, QUser.user.username, Expressions.stringTemplate("''"), QUser.user.tenantId, QUser.user.fullname, QUser.user.active, QUser.user.localeKey, GroupBy.set(perm))));
而且这比JPQL / Hibernate-ResultTransformer版本好得多。