【问题标题】:Inject attribute into JPQL SELECT clause将属性注入 JPQL SELECT 子句
【发布时间】:2011-10-28 16:11:27
【问题描述】:

让我们描述以下用例:我有一个 JPQL 查询,它使用 new 关键字动态创建数据对象。在SELECT 子句中,我想注入一个数据库不知道但查询它的层的属性。

这可能看起来像

EntityManager em; // Got it from somewhere
boolean editable = false; // Value might change, e.g. depending on current date

Query q = em.createQuery("SELECT new foo.bar.MyDTO(o, :editable) FROM MyObject o")
            .setParameter("editable", editable);

List<MyDTO> results = (List<MyDTO>) q.getResultList();

任何想法如何在 JPQL 中将这种属性或参数注入到 SELECT 子句中? JPA 和 JPA 2.0 解决方案都适用。

编辑:性能并不起关键作用,但代码的清晰度和清洁度。

【问题讨论】:

    标签: java jpa persistence jpql


    【解决方案1】:

    您是否在简单地迭代结果列表并在每个元素上调用 setter 时测量了性能问题。我猜和

    相比
    • 对数据库执行查询所需的时间(进程间调用、网络通信)
    • 使用反射将每一行转换为 MyObject 实例所需的时间
    • 使用反射将每个 MyObject 实例转换为 MyDTO 所需的时间

    你的循环会非常快。

    如果您非常关心性能,您应该从返回的 MyObject 实例手动构造您的 MyDTO 实例,而不是依赖 Hibernate 和反射来完成。

    Keep 首先是简单、安全、可读和可维护的。然后,如果您有性能问题,请测量以检测它的来源。然后,只有这样,优化。

    【讨论】:

    • 我并不是特别在意性能,而是在意好看和干净的代码。更像是一个设计目标。
    • 那么结果列表相当大的事实是无关紧要的。无论元素数量如何,循环都是相同的。我发现有一个循环构造 MyDTO 实例列表(启用重构,编译器检查安全性)比将它放在 HQL 查询中更干净,因为重构不会捕获构造函数签名中的更改并且重构将是不可能的.
    • 如果您担心重构,您根本不会使用 JPQL,而是使用 Criteria API。我编辑了我的问题以删除性能理由。让其他人更容易专注于问题的核心。
    • 我们不是在一个非黑即白的世界里。使用 JPQL 使我获得了清晰性和可读性,但使我失去了重构能力。恕我直言,在查询中嵌入 DTO 结构会使我失去重构能力和可能的性能,但不会让我获得任何东西(除了几次击键)。
    【解决方案2】:

    如果没有可能的供应商扩展,它将无法工作,因为根据规范:

    4.6.4 输入参数
    ...
    输入参数只能在 查询的 WHERE 子句或 HAVING 子句。

    【讨论】:

      猜你喜欢
      • 2012-05-22
      • 2014-08-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 2012-09-17
      • 2018-09-07
      • 2012-02-04
      • 1970-01-01
      相关资源
      最近更新 更多