我应该使用@NamedQuery 注释还是addNamedQuery 方法?

Should I use @NamedQuery annotation or addNamedQuery method?

目前,构成我的应用程序的 JPA 实体有一个 @NamedQueries 块,其中包含许多 @NamedQuery 注释。这很好用,但我的一些实体有超过 80 个 @NamedQuery 注释并且越来越难以维护。我现在需要向我的查询添加排序并且不想创建额外的@NamedQuery 注释。

在研究过程中,我发现了 JPA 2.1 EntityManagerFactory.addNamedQuery 方法。这似乎是我祈祷的答案。我可以创建一个在启动时运行的初始化程序,以使用我建立的命名约定创建我所有的命名查询,并消除实体顶部的大 @NamedQueries 块。

我什至可以使用以下 EclipseLink 特定代码来添加基于现有 NamedQuery 的新 NamedQuery。

TypedQuery<Portrait> tq = em.createNamedQuery("Portraits.read", Portrait.class);

String jpql = tq.unwrap(EJBQueryImpl.class).getDatabaseQuery().getJPQLString();

Query q = this.em.createQuery(jpql + " ORDER BY p.id DESC");

em.getEntityManagerFactory().addNamedQuery("Portraits.read.Id-D", q);

TypedQuery<Portrait> tq2 = em.createNamedQuery("Portraits.read.Id-D", Portrait.class);

有什么理由,我不应该使用 addNamedQuery 方法来代替或补充 @NamedQuery 注释?

命名查询用于组织查询定义和提高应用程序性能,因为查询字符串是在注释中定义的,不能在运行时更改,还可以防止 sql 注入等安全问题。

  • NamedQuery 的名称作用域为整个持久化单元 并且在该范围内必须是唯一的。所以也许最好定义 正如你所说,它给每个 class。因为它是未定义的应该 如果同一持久性单元中的两个查询具有相同的 名称,但很可能是应用程序的部署 将失败或一个将覆盖另一个,导致不可预测 运行时的结果。
  • 动态命名查询 (addNamedQuery) 是一种混合方法 动态创建查询,然后将其保存为命名查询 实体经理工厂。在那一点上,它变得和其他任何东西一样 可能已在元数据中静态声明的命名查询。

    这仅在少数特定情况下有用:

    • 它提供的主要优点是如果有查询直到运行时才知道,但随后重复发出。

    • 一旦动态查询成为命名查询,它只承担处理一次的成本。是在查询注册为命名查询时支付费用,还是推迟到第一次执行时支付,具体取决于具体实现。

总而言之,最好在与查询结果最直接对应的实体 class 上定义命名查询。但动态查询在某些特定点也有它们的位置。