目前,构成我的应用程序的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注释之外?
答案 0 :(得分:3)
命名查询用于组织查询定义并提高应用程序性能,因为查询字符串是在注释中定义的,不能在运行时更改,也可以防止sql注入等安全问题。
动态命名查询(addNamedQuery)是一种混合方法 动态创建一个查询,然后将其保存为命名查询 实体经理工厂。那时它变得和其他任何一样 可能已在元数据中静态声明的命名查询。
仅在少数特定情况下有用:
它提供的主要优势是,如果有查询在运行时才知道,但随后重复重新发布。
一旦动态查询成为命名查询,它将只承担一次处理的成本。它是特定于实现的,无论是在查询作为命名查询注册时支付成本,还是在第一次执行时延迟支付成本。
总结一下,最好在实体类上定义最直接对应于查询结果的namedqueries。但动态查询也在某些特定点上占有一席之地。