java QueryDsl投影元素集合
我试图弄清楚如何使用枚举列表(@ElementCollection)对实体进行DTO投影。不幸的是,缺少QueryDsl文档,在这里我只发现版本3的结果不适用于版本4
@Entity
public class User {
private String username;
@Enumerated(EnumType.STRING)
@ElementCollection(targetClass = Permission.class)
private Set<Permission> permissions;
}
我想要一个DTO,它具有权限枚举或简单字符串的集合/列表/数组(无论如何都将转换为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并返回一个映射。我正在动态地生成这些查询,我想要一个DTO列表,而不是DTO列表和映射
编辑:
如果我要编写一个本机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的看法呕吐:
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();
# 1 楼答案
下面是使用
.transform()
方法的完整示例专业人士
.select()
和.transform()
方法,使用相同的表达式数组。这意味着表达可以在一个地方李>缺点
没有分组。这意味着没有嵌套的集合
表达式顺序和DTO构造函数参数顺序应该相同
创建嵌套对象逻辑应该在DTO构造函数中
结论
可以对单级简单对象使用
.transform()
如果您需要额外的操作(作为构建分层响应结构的分组),您应该创建自己的mapper类。映射器类将接收
Collection<Tuple>
并返回List<YourDto>
或Set<YourDto>
# 2 楼答案
好吧,我终于明白了。在这种情况下,实际上必须使用transformer,这是有道理的,因为您想要聚合几行
我得把它挖出来。如果你不使用IDE,静态导入实际上会让事情变得棘手,但是像我一样在Github上阅读它。我几乎找到了解决方案,但我使用了
Expressions.set()
,而不是GroupBy.set()
:这在外观上比JPQL/Hibernate ResultTransformer版本好得多