QueryDsl投影ElementCollection

问题描述 投票:0回答:1

我正在尝试如何对带有枚举(@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();
java jpa querydsl
1个回答
0
投票

好的,我终于明白了。在这种情况下,您实际上必须使用一个转换器,因为您要聚合多行。]

我不得不深入研究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版本好得多。

© www.soinside.com 2019 - 2024. All rights reserved.