在 JPA DTO 投影查询中加载子集合 DTO

2023-11-26

我在 Wildfly 10.1.0-Final 上使用 Java EE 7 与 Java 8 和 Hibernate (5.0.X),并且需要使用投影将 JPQL 查询结果加载到 DTO 中,但我找不到任何有关如何执行此操作的文档同时加载子集合 DTO。

例如,如果我有以下用户、角色和权限实体:

@Entity
public class User
{
    @Id
    private long id;

    private String userName;
    private String firstName;
    private String lastName;

    private JobTitle jobTitle;
    private Email email;

    private boolean isRemote;

    @ManyToMany
    private Set<Tag> tags;

    @ManyToMany
    // @JoinColumn definitions...
    private Set<Role> roles;

    // getters/setters...
}

@Entity
public class Role
{
    @Id
    private long id;

    private String name;
    private String description;

    @ManyToMany
    // @JoinColumn definitions...
    private Set<Privilege> privileges;

    // getters/setters...
}

@Entity
public class Privilege
{
    @Id
    private long id;

    private String key;
    private String name;
    private String description;

    // getters/setters...
}

我想使用投影将一些查询结果加载到以下不可变的 DTO 中(假设所有 DTO 都有基于 id 实现的 hashCode 和 equals):

public class UserDTO
{
    private final long id;
    private final String userName;
    private final Set<RoleDTO> roles = new HashSet<>();

    public UserDTO(long id, String userName, Collection<RoleDTO> roles) // not sure if this is correct for projection..
    {
        this.id = id;
        this.userName = userName;
        this.roles.addAll(roles);
    }

    public Set<Role> getRoles()
    {
         return Collections.unmodifiableSet(roles);
    }

    // getters
}

public class RoleDTO
{
    private final long id;
    private final String name;
    private final Set<PrivilegeDTO> privileges = new HashSet<>();

    public RoleDTO(long id, String name, Set<PrivilegeDTO> privileges)
    {
        this.id = id;
        this.name = name;
        this.privileges.addAll(privileges);
    }

    public Set<Privilege> getPrivileges()
    {
         return Collections.unmodifiableSet(privileges);
     }
    // other getters
}

public class PrivilegeDTO
{
    private final long id;
    private final String key;

    public PrivilegeDTO(long id, String key)
    {
        this.id = id;
        this.key = key;
    }
    // getters
}

为了实现这一目标,JPQL 查询的结构是什么样的?我很确定我可以通过执行连接然后将结果处理到 DTO 对象中来完成工作,如下所示(按 ID 加载 50 个最新用户):

List<Object[]> results = em.createQuery("SELECT u.id, u.userName, r.id, "
    + "r.name, p.id, p.key FROM User u "
    + "LEFT JOIN u.roles r "
    + "LEFT JOIN r.privileges p "
    + "ORDER BY u.id DESC")
    .setMaxResults(50).getResultList();
Map<Long, UserDTO> users = new HashMap<>();
Map<Long, RoleDTO> roles = new HashMap<>();
Map<Long, PrivilegeDTO> privileges = new HashMap<>();

for(Object[] objArray : results)
{
  // process these into the DTO objects,
}

重建必须从 PrivilegeDTO 对象开始,然后是 RoleDTO,最后是 UserDTO。这将允许不变性,因为在构建 RoleDTO 对象时需要 PrivilegeDTO 对象,否则必须稍后添加它们,这意味着 RoleDTO 不是不变的。

在 Streams 中这将是一个有趣的练习,但我更希望能够从查询中构建它,看起来它必须更快。这可能吗?

多谢!


嗨,Morgan,简短的回答是否定的,您无法从查询构建,因为您无法将 JPQL 映射到 DTO 集合字段。这是一个与此相关的问题JPQL:在构造函数表达式中接收集合

无论如何,你可以尝试使用 spel 进行 Spring 投影的方法https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query.spel-expressions

但我认为正确的解决方案就是使用手动映射,就像这个答案中所解释的那样https://stackoverflow.com/a/45934668/3449039

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 JPA DTO 投影查询中加载子集合 DTO 的相关文章

随机推荐

  • Django:更新数据库架构而不丢失数据

    如果我想升级 更改 我的数据库架构 通过将新字段添加到 Django 模型中来将新字段添加到表中 而不丢失这些表中的数据 最好的解决方案是什么 syncdb 当然不会添加它们 所以我需要您的建议如何更改表而不删除它们并使用syncdb再次重
  • 使用侧列表托盘嵌入 YouTube 播放列表

    我一直在使用 javascript 使用 youtube 嵌入播放列表功能 到目前为止 当我嵌入播放列表时 它看起来像这样 http postimage org image vk6fv56yx 蓝色圆圈显示播放列表中的项目数 单击时会显示缩
  • 如何仅比较 EF 中 DateTime 的日期组件?

    我有两个日期值 一个已存储在数据库中 另一个由用户使用 DatePicker 选择 用例是从数据库中搜索特定日期 先前在数据库中输入的值始终具有 12 00 00 的时间部分 而从选择器输入的日期具有不同的时间部分 我只对日期部分感兴趣 想
  • 如何使用 root 在 Android 4.2 及更高版本上切换飞行模式?

    众所周知 在 Android 4 2 上 只有系统应用程序可以切换飞行模式 但我认为它必须适用于 root 设备 我想在我的应用程序中将其实现为具有 Build VERSION SDK INT gt 17 的 root 设备 如何在 And
  • 根据一组关键字进行搜索

    我需要根据一组关键字进行搜索 返回与这些关键字相关的所有广告 然后结果是一个类别列表 其中包含每个类别的广告计数 搜索是在 KeywordSearch 表中进行的 public class KeywordSearch public int
  • 我可以在不使用 Array 构造函数或数组文字的情况下创建 Array.isArray() 返回 true 的对象吗?

    我可以通过将其原型设置为轻松使普通对象看起来像数组Array prototype const obj Reflect setPrototypeOf obj Array prototype 我知道魔法也存在一些问题length属性和稀疏数组
  • 使用 UIScreenEdgePanGestureRecognizer 而不移动 MKMapView

    我有一个包含 MKMapView 的 UIViewController 事实上 它包含一个包含 MKMapView 的全屏容器 但它不应该有任何影响 我实现了一个 UIScreenEdgePanGestureRecognizer 以显示抽屉
  • Quantmod add_TA 和 Chart_Series 出现问题 - 调用下一个 add_TA 后线条和文本消失

    我正在使用新的chart Series and add TA非常多 它对我来说非常有效 我发现它非常有用 我正在尝试在图表上添加一些内容 水平线和一些文本 这里开始出现问题 正确绘制水平线和文本后 如果我调用后续命令 它们就会消失add T
  • Cassandra控制SSTable大小

    有没有办法控制 SSTable 的最大大小 例如 100 MB 这样当 CF 实际上有超过 100MB 的数据时 Cassandra 就会创建下一个 SSTable 不幸的是 答案并不那么简单 SSTable 的大小将受到压缩策略的影响 并
  • C语言中的限定符是什么?

    我正在这个网址阅读一些文字 https cs senecac on ca btp100 pages content varia p html 在 限定符 部分中 他们说 我们可以限定 int 类型以确保它包含最少位数 Short 至少包含
  • 在 ANSI C 中正确声明 main() 函数 [重复]

    这个问题在这里已经有答案了 C标准说 程序启动时调用的函数 被命名为主 实施情况 没有为此声明原型 功能 它应定义为 返回类型为 int 并且没有 参数 int main void 或带有两个参数 参考 这里作为 argc 和 argv 尽
  • 如何在 Isabelle/jEdit 中启用“跟踪”

    I m a vim风扇 但仅emacs有这个 Isabelle HOL 环境 jEdit很棒 但我不能使用 using simp trace true like in emacs 如何启用 跟踪 jEdit 你确实可以使用simp trac
  • 将函数应用于多维数组:R 与 MATLAB

    这个问题可以被认为与this one 这帮助我提高了 R 在计算大数组平均值时的性能 不幸的是 在这种情况下 我尝试应用更复杂的东西 例如分位数计算 我有一个包含超过 4000 万个元素的 4 维数组 我想计算特定维度上的第 66 个百分位
  • 更改 GridView 的行为以使其水平滚动而不是垂直滚动

    我想做一个UI像一个元素GridView 我希望它具有完整的功能 但希望它可以水平滚动而不是垂直滚动 通过水平滚动 我的意思是它应该以这种方式构建 而不是放在一个HorizontalScrollView 我的会是Custom GridVie
  • 在 NodeJS 中下载大文件的最佳方法是什么?

    下面的服务器代码对于 5GB 文件运行良好wget http localhost 11146 base bigFile zip但不使用客户端代码 服务器端代码 var http require http var fs require fs
  • Ninject 与 MembershipProvider |角色提供者

    我使用 ninject 作为我的 IoC 并编写了一个角色提供程序 如下所示 public class BasicRoleProvider RoleProvider private IAuthenticationService authen
  • 为什么 git rebase 会触发合并冲突?

    我已经克隆了一个远程存储库 创建了一个新分支b并开始工作并做出承诺 我也推了b分支 但我是唯一一个在这方面工作的人 一段时间后 我想在远程主分支上重新设置本地分支的基础 只是为了与系统可能发生的更改同步 请注意 我确信我是唯一处理这些特定文
  • Python 3 和 tkinter 通过单击按钮打开新窗口

    当用户单击 Tkinter 和 Python 3 中的按钮时 如何打开新窗口 您可以通过创建 Tkinter 类的新实例来打开新窗口Toplevel 例如 import Tkinter as tk class View tk Frame c
  • 将 geoJson 数据转换为 SQL Server 空间数据类型 (GIS)

    我已经从 openstreetmaps 下载了 geoJson 格式的行政边界 城市 地区 国家等 我正在尝试使用空间数据将与多边形相关的 json 数据存储在我的 MS sql 服务器中 由于我从未解析过如此复杂的 json 文件 因此我
  • 在 JPA DTO 投影查询中加载子集合 DTO

    我在 Wildfly 10 1 0 Final 上使用 Java EE 7 与 Java 8 和 Hibernate 5 0 X 并且需要使用投影将 JPQL 查询结果加载到 DTO 中 但我找不到任何有关如何执行此操作的文档同时加载子集合