3

我正在研究使用 Hibernate 作为其持久性提供程序的 J2EE 6 代码库。我的经验更多是在 Spring 中,而且我对 JPA 注释和类似的东西还很陌生,但是我在所有实体类中都注意到了很多这种情况,这让我感到惊讶——我认为 @NamedQuery 更适用于复杂的 SQL?当然,这些简单的选择(以及在休眠映射中定义的连接)可以在不写出 SQL 的情况下完成吗?

In the Entity:
@NamedQueries({
@NamedQuery(name = "DealRaw.findByrawUrl", query = "SELECT d FROM DealRaw d WHERE d.rawUrl = :rawUrl"),
@NamedQuery(name = "DealRaw.findByState", query = "SELECT d FROM DealRaw d WHERE d.state = :state"),
.... etc ....
})

接着

In the Service Class
Query qR=_em.createNamedQuery("DealRaw.findByrawUrl");  //_em is an EntityManager
qR.setParameter("rawUrl", value);
List<DealRaw> dRs=(List <DealRaw>)qR.getResultList();
4

3 回答 3

2

这些查询不是 SQL 查询,而是 JPQL 查询。您可以将任何类型的查询放在命名查询中,无论是否复杂。

它们都有相同的优点:

  • JPA引擎在启动时对查询进行解析和验证,并可能缓存解析结果以避免一次又一次的解析。
  • 相同的查询可以很容易地在代码中的几个地方使用(尽管那是有问题的设计)

它们都有相同的缺点,IMO:查询没有定义在哪里使用,因此代码更难理解。

无论这些查询是否命名,您都必须编写这些查询来执行它们。加载实体的唯一其他方法是使用它们的 ID 找到它们(这里不是这种情况),或者使用关联从一个实体导航到另一个实体(也不是这种情况)。

于 2011-10-31T17:55:19.553 回答
1

正如 JB Nizet 所说,为了找到结果集,您必须在某处编写查询。

将它们作为 NamedQuery(或 CriteriaQuery,如果那是您的事情)的一个好处是您可以保护自己免受 SQL 注入。如果查询是在代码中使用字符串连接(例如String query = "SELECT d FROM DealRaw d WHERE d.rawUrl = '" + rawUrl + "'";甚至使用命名参数)动态创建的,那么将来的一些程序员可能会出现并以允许 SQL 注入的方式修改查询(如示例中所示)。

是的,有一些方法可以在使用串联代码构造的查询中使用命名参数,但这并不能像预定义的命名查询那样保护您。

于 2011-10-31T19:02:28.760 回答
1

为什么不使用 Criteria 而不是 NamedQuery?过滤会容易很多。在某些情况下,创建标准会变得非常混乱和困难,但是对于单列,我相信这是最简单的选择。

于 2011-10-31T18:10:54.357 回答