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

时间:2017-11-22 10:25:19

标签: jpa java-ee eclipselink

目前,构成我的应用程序的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注释或者除了@NamedQuery注释之外?

1 个答案:

答案 0 :(得分:3)

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

  • NamedQuery的名称范围限定为整个持久性单元 并且必须在该范围内是唯一的。因此,定义可能更好 就像你说的那样,每个班级。因为它未定义应该是什么 如果同一持久性单元中的两个查询具有相同的结果,则会发生 名称,但很可能是部署应用程序 会失败或者会覆盖另一个,导致不可预测 结果在运行时。
  • 动态命名查询(addNamedQuery)是一种混合方法 动态创建一个查询,然后将其保存为命名查询 实体经理工厂。那时它变得和其他任何一样 可能已在元数据中静态声明的命名查询。

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

    • 它提供的主要优势是,如果有查询在运行时才知道,但随后重复重新发布。

    • 一旦动态查询成为命名查询,它将只承担一次处理的成本。它是特定于实现的,无论是在查询作为命名查询注册时支付成本,还是在第一次执行时延迟支付成本。

总结一下,最好在实体类上定义最直接对应于查询结果的namedqueries。但动态查询也在某些特定点上占有一席之地。