我应该使用 @NamedQuery 注释还是 addNamedQuery 方法?
Posted
技术标签:
【中文标题】我应该使用 @NamedQuery 注释还是 addNamedQuery 方法?【英文标题】:Should I use @NamedQuery annotation or addNamedQuery method? 【发布时间】:2017-11-22 10:25:18 【问题描述】:目前,构成我的应用程序的 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 注释之外?
【问题讨论】:
您“应该”做什么取决于您的项目和用例。没有“答案”。这是你的项目,你自己决定。哦,在你的例子中,“JPQL”不是“sql”,所以不要调用那个变量,否则你会把维护你的项目的人搞糊涂 我想看看是否有人会说“不要使用 addNamedQuery 因为......”我在网上没有找到太多关于这种方法的信息,所以我担心我错过了一个明显的理由不使用它。您的评论让我更加相信方法方法是有效的。根据您的建议,我将 sql 更改为 jpql。谢谢! 您可能会发现在orm.xml
文件中更易于管理命名查询。
我知道有很多人认为 jpql-statements 有点特别,应该将它们保存在一个非常特别的中心位置。我不太相信这种方法。恕我直言,最好在 java-source-code 本身中查看用于提供数据的查询。你的问题更支持我的观点。
【参考方案1】:
命名查询用于组织查询定义和提高应用程序性能,因为查询字符串定义在注解中,不能在运行时更改,还可以防止像sql注入这样的安全问题。
NamedQuery 的名称范围是整个持久性单元 并且在该范围内必须是唯一的。所以也许更好地定义 正如你所说,它适用于每一堂课。因为它是未定义的 如果同一持久性单元中的两个查询具有相同的 名称,但很可能是应用程序的任一部署 将失败或一个将覆盖另一个,导致不可预测 运行时的结果。动态命名查询 (addNamedQuery) 是一种混合方法 动态创建查询,然后将其保存为命名查询 实体管理器工厂。在那一点上,它变得和其他任何东西一样 可能已在元数据中静态声明的命名查询。
这仅在少数特定情况下有用:
它提供的主要优势是,如果存在直到运行时才知道的查询,但随后会重复发出。
一旦动态查询成为命名查询,它将只承担处理一次的成本。该成本是在查询注册为命名查询时支付,还是推迟到第一次执行时支付,具体取决于实现。
总而言之,最好在与查询结果最直接对应的实体类上定义命名查询。但动态查询在某些特定点也有其一席之地。
【讨论】:
谢谢!我将采用混合方法继续前进。我的 JPA 实体类将在类的顶部定义核心命名查询,但我将使用动态名称查询将排序信息附加到核心查询。例如,用户在 PrimeFaces 数据表上选择排序;客户端请求排序的数据,服务器使用现有的命名查询或通过将排序信息附加到现有的命名查询来构建新的命名查询。以上是关于我应该使用 @NamedQuery 注释还是 addNamedQuery 方法?的主要内容,如果未能解决你的问题,请参考以下文章
将@NamedQuery 用于单列选择(J2EE/JPA、Hibernate)是一种好习惯吗?